Navigation Example

Sample application demonstrating how to integrate the VisioDevKit into an application.

  1. Objectives
  2. Description
  3. Architecture
  4. Things to try
  5. Relevant Example Files

Objectives

The main objective of the navigation sample is to demonstrate a full featured application which demonstrates the various features of VisioDevKit.

Description

The navigation sample demonstrates the following functionality:

Architecture

Below is a description of the architecture that has been used for the Visioglobe sample application. This approach may not suit everyones needs, however we've found it to be extremely useful. The first advantage is that it's easier to develop across different platforms. Secondly, it's extremely useful for plugging different functionality into the application for testing and demonstration purposes.

The architecture of the Navigation Sample can be broken into the following components.

VgMyMainActivity

This component is responsible for creating the VgMySurfaceView, the VgMyBasicApplicationController and any Blocks that are desired to be associated with the VgMyBasicApplicationController.

Some blocks have a dependency on modules. For example a block which creates a route will not be very effective if the routing module isn't available. Therefore it's generally a good idea for the VgMyMainActivity to verify that a dependent module is available before creating the block and registering it with the VgMyBasicApplicationController.

VgMySurfaceView

The surface view which provides the window to the VisioDevKit. See Under the hood for an overview.

VgMyBasicApplicationController

The component controls the communication between the registered Blocks and the VisioDevKit

Blocks

A block represents a set of functionality that is recognized by the VgMyBasicApplicationController. The blocks must implement an interface in order to be registered with the VgMyBasicApplicationController. Once registered, the VgMyBasicApplicationController will use that interface to communicate with the block.

For simplicity some blocks which are available in the sample may not be mentioned below.

VgMyBubbleView

A bubble view can be displayed and associated with a place within the map.

VgMyNavigationHelper

Provides a mechanism to create a navigation item.

VgMyRouteHelper

Provides a mechanism to create and display a route on the map.

VgMyInsructionView

Displays an instruction view which is associated with a navigation.

VgMyStackedLayerAndCameraHandler

Provides a vertical animation for moving between layers within a map. There are two types of views. The first is a global view which provides an overview of all the possible layers. Then there is a detailed view, which zooms in on one particular view.

VisioSampleClassDiagram.jpg

Start up

The below diagrams show the work flow for the start up of the sample applications. The goal of start up is to ensure that the map bundle used by the application is the latest version available on the map server. If a newer version of the map bundle is available, the application will prompt the user if they would like to download the new version of the map bundle.

Android

VisioSampleAndroidStartupDiagram.jpg

iOS

VisioSampleIosStartupDiagram.jpg

Things to try

The number of customizations that can be performed to the Sample Application are endless. However, we've provided a list of common things the users generally like to customize.

Relevant Example Files

Android Specific Files

./navigationModule/Makefiles/Android/src/com/visioglobe/VisioNavigationSample/VgMyMapActivity.java

/*
 * Copyright 2011, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

package com.visioglobe.VisioNavigationSample;

import java.io.File;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

import javax.microedition.khronos.opengles.GL10;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.Toast;
import android.widget.ToggleButton;

import com.visioglobe.VisioSample.R;
import com.visioglobe.VisioSample.VgMyBasicApplicationController;
import com.visioglobe.VisioSample.VgMyConfigPreferences;
import com.visioglobe.VisioSample.VgMyGeometryManager;
import com.visioglobe.VisioSample.VgMySurfaceView;
import com.visioglobe.VisioSample.VgMyTextureLoader;
import com.visioglobe.VisioSample.Blocks.VgMyAvatarDisplay;
import com.visioglobe.VisioSample.Blocks.VgMyBubbleView;
import com.visioglobe.VisioSample.Blocks.VgMyInstructionView;
import com.visioglobe.VisioSample.Blocks.VgMyMapManagerListParser;
import com.visioglobe.VisioSample.Blocks.VgMyNavigationHelper;
import com.visioglobe.VisioSample.Blocks.VgMyPlaceConfigurationSetter;
import com.visioglobe.VisioSample.Blocks.VgMyRemoteMapManagerImpl;
import com.visioglobe.VisioSample.Blocks.VgMyRoutingHelper;
import com.visioglobe.VisioSample.Blocks.VgMySimulatedLocationProvider;
import com.visioglobe.VisioSample.Blocks.VgMyStackedLayerAndCameraHandler;
import com.visioglobe.VisioSample.Interfaces.VgMyInstructionUpdateListener;
import com.visioglobe.VisioSample.Interfaces.VgMyLayerAndCameraHandler;
import com.visioglobe.VisioSample.Interfaces.VgMyLayerAndCameraListener;
import com.visioglobe.VisioSample.Interfaces.VgMyLocationListener;
import com.visioglobe.VisioSample.Interfaces.VgMyLocationProvider;
import com.visioglobe.VisioSample.Interfaces.VgMyRemoteMapManager;
import com.visioglobe.VisioSample.Interfaces.VgMyRemoteMapManager.VgMyRemoteMapManagerCallback;
import com.visioglobe.VisioSample.Interfaces.VgMyRemoteMapManager.VgMyRemoteMapManagerConfig;
import com.visioglobe.VisioSample.Interfaces.VgMyRouteCreator;
import com.visioglobe.VisioSample.Utils.InstallActivity;
import com.visioglobe.libVisioDevKit.VgErrorCode;
import com.visioglobe.libVisioDevKit.VgIDatabase;
import com.visioglobe.libVisioDevKit.VgLayerVector;


public class VgMyMapActivity 
    extends 
        Activity
    implements 
        VgMySurfaceView.VgMySurfaceViewListener,
        VgMyLayerAndCameraListener
{

    private class LayerSpinnerOnItemSelectedListener implements AdapterView.OnItemSelectedListener 
    {       
        // A mechanism which prevents any action to be taken upon an onItemSelected event.
        // This stop message bouncing between the SDK and the layer spinner when changing layers
        public boolean mIgnoreNextEvent = false;
        
        //Selects the layer corresponding to the clicked item.
        public void onItemSelected(AdapterView<?> pAdapterView, View pView, final int pItemIdx, long pItemId) 
        {
            if(true == mIgnoreNextEvent)
            {
                mIgnoreNextEvent = false;
            }
            else
            {
                final String lLayerName = (String)mLayerSpinner.getItemAtPosition(pItemIdx);
                mSurfaceView.queueEvent(new Runnable() 
                {
                    public void run() 
                    {
                        mBasicAppController.gotoLayer(lLayerName, true);
                    }
                });
            }
        }

        public void onNothingSelected(AdapterView<?> pAdapterView) 
        {}
    }
    
    
    class VgMyControllerRemoteMapManagerCallback implements VgMyRemoteMapManagerCallback
    {
        String mMapName;
        VgMyMapManagerListParser.Entry mEntry;
        
        public VgMyControllerRemoteMapManagerCallback(String pMapName)
        {
            mMapName = pMapName;
        }
        
        public void listFinished(final VgMyRemoteMapManager pRemoteMapManager, ErrorCode pErrorCode, VgMyMapManagerListParser pListParser)
        {
            mEntry = null;
            if( (ErrorCode.eSuccess == pErrorCode) &&
                (true == pListParser.isValid()) )
            {
                while(false == (pListParser.finished()))
                {
                    VgMyMapManagerListParser.Entry lEntry = pListParser.getNext();

                    if(lEntry.mName.contentEquals(mMapName))
                    {
                        mEntry = lEntry;
                        
                        
                        // Check if the server version is more recent then the current local version
                        if( (0 == mConfigPreferences.mVersion.length()) || 
                            (true == VgMyMapActivity.isVersion1OlderThanVersion2(mConfigPreferences.mVersion, lEntry.mVersion)) )   
                        {
                            // Display prompt
                            AlertDialog.Builder builder = new AlertDialog.Builder(VgMyMapActivity.this);
                            builder.setMessage(R.string.requestDownloadMapConfirmation);
                            // Add the buttons
                            builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() 
                            {
                                @Override
                                public void onClick(DialogInterface dialog, int which) 
                                {
                                    pRemoteMapManager.downloadMap(mEntry.mID);
                                }
                            });
                            builder.setNegativeButton("No", new DialogInterface.OnClickListener() 
                            {
                                @Override
                                public void onClick(DialogInterface dialog, int which) 
                                {
                                    loadLocalMap(mConfigPreferences);
                                }
                            });

                            // Create the AlertDialog
                            AlertDialog dialog = builder.create();
                            dialog.show();
                        }
                        else
                        {
                            Toast.makeText(VgMyMapActivity.this.getApplicationContext(), "Local map is up to date", Toast.LENGTH_LONG).show();
                            
                            loadLocalMap(mConfigPreferences);
                        }
                    }
                }
                
                if(null == mEntry)
                {
                    Toast.makeText(VgMyMapActivity.this.getApplicationContext(), "List downloaded from map server does not contain map: " + mMapName, Toast.LENGTH_LONG).show();
                }
            }
            else
            {
                Toast.makeText(VgMyMapActivity.this.getApplicationContext(), "List finished with errors", Toast.LENGTH_LONG).show();
            }
        }
        
        public void mapDownloadFinished(VgMyRemoteMapManager pRemoteMapManager, ErrorCode pErrorCode, long pMapID)
        {
            if(ErrorCode.eSuccess == pErrorCode)
            {
                VgMyConfigPreferences lPreferences = new VgMyConfigPreferences();
                lPreferences.mConfigurationFile = pRemoteMapManager.getLocalConfigPathForMap(pMapID); 
                lPreferences.mLicenseURL = "http://license.visioglobe.com/renew/" + mEntry.mLicenseID;
                lPreferences.mSecret = mEntry.mSecretCode;
                lPreferences.mVersion = mEntry.mVersion;
                
                if(true == verifyMyMap(lPreferences) )
                {
                    lPreferences.save(VgMyMapActivity.this);
                    mConfigPreferences = lPreferences;
                    loadMap(mConfigPreferences);
                }
            }
            else
            {
                Toast.makeText(VgMyMapActivity.this.getApplicationContext(), "Map downloaded finished with errors", Toast.LENGTH_LONG).show();
            }
            
        }
    };  // VgMyControllerRemoteMapManagerCallback
    
    
    private class SwitchViewOnClickListener implements OnClickListener
    {
        public void onClick(View arg0) 
        {
            mSurfaceView.queueEvent(new Runnable() 
            {
                public void run() 
                {
                    if(null != mBasicAppController)
                    {
                        if (mBasicAppController.isGlobalView()) 
                        {
                            mBasicAppController.switchToDetailedView(true);
                        }
                        else
                        {
                            mBasicAppController.switchToGlobalView(true);
                        }
                    }
                }
            });
        }
    }
    
    private class AvoidStairsOnClickListener implements OnClickListener
    {
        public void onClick(View arg0) 
        {
            ToggleButton lAvoidStairsButton = (ToggleButton)arg0;
            final boolean lSetAvoidStairs = lAvoidStairsButton.isChecked();
            
            mSurfaceView.queueEvent(new Runnable() 
            {
                public void run() 
                {
                    
                    if(null != mBasicAppController)
                    {
                        mBasicAppController.setAvoidStairs(lSetAvoidStairs);
                    }
                }
            });
        }
    }
    
    // Request codes
    public static final int INSTALL_MAP_BUNDLE_REQUEST = 0;
    
    // FIELDS
    protected VgMySurfaceView mSurfaceView = null;
    protected VgMyBasicApplicationController mBasicAppController = null;
    protected VgMyTextureLoader mTextureLoader = null;
    protected VgMyGeometryManager mGeometryManager = null;
    VgMyStackedLayerAndCameraHandler mLayerAndCameraHandler = null;
    protected VgMyRemoteMapManagerImpl mVgMyRemoteMapManager = null;
    
    protected VgMyLocationProvider mLocationProvider = null;
    
    // The spinner for layer selection
    private Spinner mLayerSpinner;
    private ArrayAdapter<String> mLayersAdapter;
    // The spinner's listener for changing layers 
    private LayerSpinnerOnItemSelectedListener mLayerSpinnerListener = null;
    // For switching between the global and detailed views
    // Note: This button will only be shown when it's possible to view the global view.  If there is only
    // one layer in the dataset, then the global view is not available.
    private ImageView mSwitchViewButton;
    // Enable to avoid stairs in computed routes.
    private Button mAvoidStairsRouting;
    
    // Will be true up until the first loadConfiguration, after which it will remain false. 
    protected boolean mIsStartUp = true;

    // Configuration preferences for the active map bundle
    private VgMyConfigPreferences mConfigPreferences;
    
        
    // METHODS
    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        // Create's the VgMySurfaceView
        createMainLayout();
        
        // For debugging, reset preferences to simulate first launch of application.
        //VgMyConfigPreferences.reset(this);
        
        
        // IMPORTANT:
        // The below map config details refer to the map embedded within your application.
        // The integrator is responsible for updating these values to correctly correspond with
        // the map embedded within the application.
        // Note: the configuration file is determined once the local map bundle
        // has been extracted to the sd card
        VgMyConfigPreferences lEmbeddedMapConfig = new VgMyConfigPreferences();
        lEmbeddedMapConfig.mSecret = 0L;
        lEmbeddedMapConfig.mConfigurationFile = "";
        lEmbeddedMapConfig.mVersion = "20120905";
        
        
        // Retrieve the current map configuration from preferences.
        mConfigPreferences = VgMyConfigPreferences.getFromPreferences(this);
        
        // If there is no map config stored in preferences 
        if((null == mConfigPreferences) ||
           (true == VgMyMapActivity.isVersion1OlderThanVersion2(mConfigPreferences.mVersion, lEmbeddedMapConfig.mVersion )) )
        {
            // Then use the embedded map configuration
            // Note: in this case, the map will always be (re-)installed from the assets directory
            // because the reference to mConfigurationFile is empty.
            mConfigPreferences = lEmbeddedMapConfig;
        }
        
        // Load map from network
        loadFromNetwork();
        
        // If application isn't connected to the Visio map manager web service, 
        // then you can remove the call to loadFromNetwork with uncomment the 
        // method below to load directly the local map.
        //loadLocalMap(mConfigPreferences);
    }

    
    public void loadFromNetwork()
    {
        if(null == mVgMyRemoteMapManager )
        {
            /*
             * IMPORTANT:
             * The below information relates to the Visioglobe Map Manager
             * REST web service.
             * If you have your own account with the Map Manager web service,
             * then you will want to update below with your details (which will be  
             * provided by Visioglobe).
             */
            VgMyRemoteMapManagerConfig lConfig = new VgMyRemoteMapManagerConfig();
            String lMapName = "Data.Generic.sg2";
            lConfig.mUsername = "sample-map-generic";
            lConfig.mPassword = "sample-map-generic";
            lConfig.mServerURL = "https://mapmanager.visioglobe.com/public/";
            lConfig.mCallback = new VgMyControllerRemoteMapManagerCallback(lMapName);
            
            String lStoragePath = VgMyMapActivity.this.getPathStorage();
            String lTempPath = VgMyMapActivity.this.getPathTemp();
            
            mVgMyRemoteMapManager = new VgMyRemoteMapManagerImpl(VgMyMapActivity.this,
                    mSurfaceView.getApplication(),
                    lConfig,
                    lStoragePath,
                    lTempPath);

        }

        if(false == mVgMyRemoteMapManager.list() )
        {
            Toast.makeText(VgMyMapActivity.this.getApplicationContext(), "Request to download list failed", Toast.LENGTH_LONG).show(); 
        }       
    }
    
    public void unloadMap() 
    {
        if(null != mSurfaceView)
        {           
            mSurfaceView.pauseRendering();
            mSurfaceView.onPause();
            mSurfaceView.setVisibility(View.GONE);
            
            // Block the gl thread to ensure that the map objects are correctly unloaded
            // before continuing.
            final boolean[] lResultStore = new boolean[1];
            FutureTask<boolean[]> lBlockOnGLThread = new FutureTask<boolean[]>(new Runnable()
            {
                public void run()
                {
                    if(null != mBasicAppController)
                    {
                        mBasicAppController.disable(); // Disable positioning
                        mBasicAppController.hideAnchoredDisplay();
                        mBasicAppController.hideInstructionDisplays();
                        mBasicAppController.hideNavigationPositionDisplays();
                        mBasicAppController.hideRouteDisplay();
                        mBasicAppController.clearRouteDisplay();
                        mBasicAppController.clearInstructionDisplays();
                        mBasicAppController.clearNavigationPositionDisplays();
                        mBasicAppController.reinitAppBlocks();

                        mBasicAppController = null;
                        mTextureLoader = null;
                        mGeometryManager = null;
                        mLayerAndCameraHandler = null;
                    }
                    lResultStore[0] = true;
                }
            }, lResultStore);

            mSurfaceView.queueEvent(lBlockOnGLThread);

            boolean[] lResultReturn = new boolean[1];
            try {
                lResultReturn = lBlockOnGLThread.get();
            } 
            catch (Exception e) 
            {
                e.printStackTrace();
            }   
        }
    }


    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) 
    {
        switch (requestCode) 
        {
        case INSTALL_MAP_BUNDLE_REQUEST: 
        {
            if (resultCode == RESULT_OK)
            {
                // Get config file name from preferences
                SharedPreferences lPrefs = getSharedPreferences(VgMyBasicApplicationController.mscPreferencesFile, Activity.MODE_PRIVATE);
                mConfigPreferences.mConfigurationFile = lPrefs.getString(VgMyBasicApplicationController.mscConfigFileDir, "vg_config.xml");
                
                if(true == verifyMyMap(mConfigPreferences))
                {
                    mConfigPreferences.save(this);
                    loadMap(mConfigPreferences);
                }
            }
            else
            {
                finish();
            }
            break;
        }
        default:
        {
            // If the VgMyMapActivity class didn't handle the activity result, it's
            // given to the VgMyRemoteManager for handling. 
            if(null != mVgMyRemoteMapManager)
            {
                mVgMyRemoteMapManager.onActivityResult(requestCode, resultCode, data);
            }
        }
        }
    }
    
    public void createMainLayout() 
    {
        LayoutInflater inflater = LayoutInflater.from(this);    // Do not use getApplicationContext here. Not supported on 2.3.6 and lower
        inflater.inflate(R.layout.main_layout, (ViewGroup) findViewById(android.R.id.content), true);
        
        mSurfaceView = (VgMySurfaceView) findViewById(R.id.VgSurfaceView);
         
        // Note the spinner is set up later (once the number of floors in the bundle is known).
        mLayerSpinner = (Spinner) findViewById(R.id.LayerSpinner);
        
        // Do not use getApplicationContext here. Not supported on 2.3.6 and lower
        mLayersAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item);
        mLayersAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

        mSwitchViewButton = (ImageView) findViewById(R.id.SwitchViewButton);
        mSwitchViewButton.setVisibility(View.INVISIBLE);
        
        mAvoidStairsRouting = (Button) findViewById(R.id.buttonAvoidStairsRouting);
    }
    
    
    @Override
    protected void onResume() 
    {
        super.onResume();

        mSwitchViewButton.setOnClickListener(new SwitchViewOnClickListener());
        mAvoidStairsRouting.setOnClickListener(new AvoidStairsOnClickListener());
        mLayerSpinner.setOnItemSelectedListener(new LayerSpinnerOnItemSelectedListener());
        
        if (mSurfaceView != null)
        {
            mSurfaceView.resumeRendering();
            mSurfaceView.onResume();
        }
    }

    @Override
    protected void onPause() 
    {
        super.onPause();
        
        mSwitchViewButton.setOnClickListener(null);
        mAvoidStairsRouting.setOnClickListener(null);
        mLayerSpinner.setOnItemSelectedListener(null);
        
        if (mSurfaceView != null) 
        {
            mSurfaceView.pauseRendering();
            mSurfaceView.onPause();
        }
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu pMenu) 
    {
        getMenuInflater().inflate(R.menu.routing_menu, pMenu);
        getMenuInflater().inflate(R.menu.navinjectstop_menu, pMenu);
        getMenuInflater().inflate(R.menu.navinjectstart_menu, pMenu);
        getMenuInflater().inflate(R.menu.reset_config, pMenu);
        return super.onCreateOptionsMenu(pMenu);
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu pMenu) 
    {
        MenuItem lMenuStopItem = pMenu.findItem(R.id.menuItemStopInjectPosition);
        MenuItem lMenuStartItem = pMenu.findItem(R.id.menuItemStartInjectPosition);
        MenuItem lMenuRoutingItem = pMenu.findItem(R.id.menuItemClearRoute);
        
        // A FutureTask is useful when it's absolutely necessary to get a result from the
        // GL thread from within the UI thread.
        // -- Format of expected results --
        // lResultStore[0] isVisibleRouteDisplay
        // lResultStore[1] isLocationProviderEnabled
        final boolean[] lResultStore = new boolean[2];
        FutureTask<boolean[]> lRetrieveStateValuesFromGLThread = new FutureTask<boolean[]>(new Runnable()
        {
            public void run()
            {
                lResultStore[0] = false;
                lResultStore[1] = false;
                if(null != mBasicAppController)
                {
                    lResultStore[0] = mBasicAppController.isVisibleRouteDisplay();
                    lResultStore[1] = mBasicAppController.isEnabled();
                }
            }
        }, lResultStore);
        
        mSurfaceView.queueEvent(lRetrieveStateValuesFromGLThread);
        
        boolean[] lResultReturn = new boolean[2];
        try {
            lResultReturn = lRetrieveStateValuesFromGLThread.get();
        } 
        catch (InterruptedException e) 
        {
            e.printStackTrace();
        } 
        catch (ExecutionException e) 
        {
            e.printStackTrace();
        }
        
        boolean lIsVisibleRouteDisplay = lResultReturn[0];
        boolean lIsLocationProviderEnabled = lResultReturn[1];
        
        if ( lIsVisibleRouteDisplay )
        {
            lMenuRoutingItem.setEnabled(true);
        }
        else
        {
            lMenuRoutingItem.setEnabled(false);
        }
        
        if(lIsLocationProviderEnabled)
        {
            lMenuStopItem.setVisible(true);
            lMenuStopItem.setEnabled(true);
            lMenuStartItem.setVisible(false);
            
        } 
        else 
        {
            lMenuStopItem.setVisible(false);
            lMenuStartItem.setVisible(true);
            lMenuStartItem.setEnabled(true);
        }

        return super.onPrepareOptionsMenu(pMenu);
    }

    public boolean onOptionsItemSelected(MenuItem pItem)
    {
        if (!super.onOptionsItemSelected(pItem))
        {
            switch (pItem.getItemId())
            {
                case R.id.menuItemClearRoute:
                {                   
                    mSurfaceView.queueEvent(new Runnable() 
                    {
                        public void run() 
                        {
                            if(mBasicAppController != null)
                            {
                                mBasicAppController.clearNavigationPositionDisplays();                          
                                mBasicAppController.clearRouteDisplay();
                                mBasicAppController.clearInstructionDisplays();
                            }
                        }
                    });
                    
                }
                    return true;
        
                case R.id.menuItemStartInjectPosition: 
                {
                    mSurfaceView.queueEvent(new Runnable() 
                    {
                        public void run() 
                        {
                            if(mBasicAppController != null)
                            {
                                mBasicAppController.showNavigationPositionDisplays();
                                mBasicAppController.enable();
                            }
                        }
                    });
                    
                }
                    return true;
                case R.id.menuItemStopInjectPosition: 
                {
                    mSurfaceView.queueEvent(new Runnable() 
                    {
                        public void run() 
                        {
                            if(mBasicAppController != null)
                            {
                                mBasicAppController.hideNavigationPositionDisplays();
                                mBasicAppController.disable();
                            }
                        }
                    });
                }
                return true;
                case R.id.menuItemResetConfig:
                {
                    VgMyConfigPreferences.reset(this);

                    Log.i("VisioDevKit", "Simulating restart of the application to see the changes, this code is for development only");
                    
                    // This is a simple way to "restart" the application,
                    Intent intent = getIntent();
                    finish();
                    startActivity(intent);
                }
                    return true;
                default:
                    return false;
            }
        }
        return true;
    }
    
    public void createLocalObjects()
    {
        mTextureLoader = new VgMyTextureLoader((Activity)this, mSurfaceView);
        
        mGeometryManager = new VgMyGeometryManager(mSurfaceView);
        
        mBasicAppController = new VgMyBasicApplicationController((Activity)this, mSurfaceView);
    }
    
    
    public boolean verifyMyMap(final VgMyConfigPreferences pConfig)
    {
        boolean isMapValid = false;
        final VgMySurfaceView lSurfaceView = new VgMySurfaceView(this.getApplicationContext());

        // A FutureTask is useful when it's absolutely necessary to get a result from the
        // GL thread from within the UI thread.
        // -- Format of expected results --
        // lResultStore[0] isMapValid
        final boolean[] lResultStore = new boolean[1];
        FutureTask<boolean[]> lRetrieveResultFromGLThread = new FutureTask<boolean[]>(new Runnable()
        {
            public void run()
            {
                VgIDatabase lDatabase = lSurfaceView.getApplication().editEngine().editDatabase();
                boolean lIsValid = false;

                if(true == lDatabase.loadConfiguration(pConfig.mConfigurationFile, pConfig.mSecret, pConfig.mLicenseURL))
                {
                    lIsValid = true;
                }
                else
                {
                    VgErrorCode lErrorCode = lSurfaceView.getApplication().editEngine().getLastError();
                    String lErrorStr = lSurfaceView.getApplication().editEngine().getErrorString(lErrorCode);
                    final String lError = "loadConfiguration failed: " + lErrorStr;
                    
                    runOnUiThread(new Runnable() {
                        public void run()
                        {
                            Toast.makeText(VgMyMapActivity.this.getApplicationContext(), lError, Toast.LENGTH_LONG).show();
                        }
                    });
                }
                lResultStore[0] = lIsValid;
            }
        }, lResultStore);

        lSurfaceView.queueEvent(lRetrieveResultFromGLThread);

        boolean[] lResultReturn = new boolean[1];
        try {
            lResultReturn = lRetrieveResultFromGLThread.get();
        } 
        catch (Exception e) 
        {
            e.printStackTrace();
        } 

        isMapValid = lResultReturn[0];
        return isMapValid;
        
    }
    
    public void loadLocalMap(VgMyConfigPreferences pConfig)
    {
        // Load from shared preferences
        if(pConfig.mConfigurationFile.length() > 0 )
        {
            loadMap(pConfig);
        }
        // Otherwise this is the first time the application has been launched.
        else
        {
            // Active the below block in order to extract and load the map bundle from the asset directory.
            Intent lIntent = new Intent(VgMyMapActivity.this, InstallActivity.class);
            
            lIntent.putExtra(VgMyBasicApplicationController.mscPreferenceID, VgMyBasicApplicationController.mscPreferencesFile);
            startActivityForResult(lIntent, INSTALL_MAP_BUNDLE_REQUEST);
        }
    }
    
    public void loadMap(final VgMyConfigPreferences pConfig)
    {
        mSurfaceView.addSurfaceViewListener((VgMySurfaceView.VgMySurfaceViewListener)this);
        
        mSurfaceView.setVisibility(View.VISIBLE);
        
        mSurfaceView.queueEvent(new Runnable() 
        {
            public void run() 
            {
                createLocalObjects();
                /*
                 * Setup the configurable aspects of the application controller.  
                 * Important: These need to be set after the VgMySurfaceView has been created 
                 */
                mBasicAppController.setConfigurationFile(pConfig.mConfigurationFile);
                mBasicAppController.setLicenseUrl(pConfig.mLicenseURL);
                mBasicAppController.setSecretCode(pConfig.mSecret);
                
                // Uses the parameters set above to setup and load the map configuration 
                if(mBasicAppController.setup())
                {

                    mSurfaceView.resumeRendering();

                    // Setup the application blocks
                    setupAppBlocks();
                    
                    // Setup the layer spinner which allows the user to change 
                    // the current layer via a native gui.
                    setupLayerSpinner();

                    // Print the VisioDevKit version only once at the first time configuration is loaded.
                    if (mIsStartUp) 
                    {
                        Log.i("VisioDevKit", "VisioDevKit version:" + mSurfaceView.getApplication().editEngine().editLicenseManager().getVersion());
                        mIsStartUp = false;
                    }

                    mBasicAppController.gotoLayer(0, false);

                    if (mSurfaceView.getApplication().editEngine().editLayerManager().getLayers().size() > 1)
                    {
                        mLayerAndCameraHandler.switchToGlobalView(false);
                    }
                    else
                    {
                        mLayerAndCameraHandler.switchToDetailedView(false);
                    }

                }
            }
        });
    }
    
    
    static boolean isVersion1OlderThanVersion2(String pVersion1, String pVersion2)
    {
        boolean lResult = false;
        
        Integer lCompareResult = pVersion1.compareTo(pVersion2);
        
        // lCompareResult will be a negative integer if the first non-equal character in this string 
        // has a Unicode value which is less than the Unicode value of the character at the same 
        // position in the specified string, or if this string is a prefix of the specified string. 
        if(0 > lCompareResult)
        {
            lResult = true;
        }
            
        return lResult;
    }

    public void setupAppBlocks()
    {
        // Verify the VisioDevKit is valid before setting up the basic app controller
        if(mBasicAppController.isVisioDevKitValid())
        {
            VgLayerVector lLayers = mSurfaceView.getApplication().editEngine().editLayerManager().editLayers();
            
            if(lLayers.size() > 0)
            {
                
                if(lLayers.size() > 1 )
                {
                    // VgMyLayerAndCameraListener events are related to the changing of layers.  Only need to register
                    // for these events when there is more then one layer in the dataset.
                    mBasicAppController.addLayerAndCameraListener((VgMyLayerAndCameraListener)this);
                }

                mLayerAndCameraHandler = new VgMyStackedLayerAndCameraHandler(mSurfaceView, (VgMyLayerAndCameraListener)mBasicAppController, mSurfaceView.getWidth(), mSurfaceView.getHeight());    
                mBasicAppController.setLayerAndCameraHandler((VgMyLayerAndCameraHandler) mLayerAndCameraHandler);

                configureStackedLayerAndCameraHandler();

                if(true == mBasicAppController.hasMapModule())
                {
                    ViewGroup lViewGroup = (ViewGroup)findViewById(R.id.SurfaceViewFrame);
                    VgMyBubbleView lBubbleView = new VgMyBubbleView((Activity)this, (VgMyRouteCreator)mBasicAppController, mSurfaceView, lViewGroup);
                    mBasicAppController.setAnchoredDisplay(lBubbleView);
                    mBasicAppController.addLayerAndCameraListener((VgMyLayerAndCameraListener)lBubbleView);

                    VgMySimulatedLocationProvider lLocationProvider = new VgMySimulatedLocationProvider((Activity)this, mSurfaceView, (VgMyLayerAndCameraHandler)mBasicAppController);
                    lLocationProvider.setListener((VgMyLocationListener) mBasicAppController);
                    mBasicAppController.setLocationProvider(lLocationProvider);
                    
                    // Configure place names/icons
                    VgMyPlaceConfigurationSetter lPlaceConfigSetter = new VgMyPlaceConfigurationSetter(mSurfaceView, mTextureLoader, this);
                    lPlaceConfigSetter.configurePlaces();
                    lPlaceConfigSetter.release();
                }

                if(true == mBasicAppController.hasRoutingModule())
                {
                    VgMyRoutingHelper lRoutingHelper = new VgMyRoutingHelper(mSurfaceView, mTextureLoader, mGeometryManager, mBasicAppController.mRouteCallback, (VgMyLayerAndCameraHandler)mBasicAppController);
                    mBasicAppController.setRouteCreator(lRoutingHelper);
                    mBasicAppController.setRouteDisplay(lRoutingHelper);
                }

                if(true == mBasicAppController.hasNavigationModule())
                {
                    VgMyNavigationHelper lNavigationHelper = new VgMyNavigationHelper((Activity)this, mSurfaceView);
                    mBasicAppController.setNavigationCreator(lNavigationHelper);

                    FrameLayout lInstructionLayoutContainer = (FrameLayout)this.findViewById(R.id.SurfaceViewFrame);
                    VgMyInstructionView lInstructionView = new VgMyInstructionView((Activity)this, (VgMyInstructionUpdateListener)mBasicAppController, mSurfaceView, lInstructionLayoutContainer);
                    mBasicAppController.addInstructionDisplay(lInstructionView);

                    VgMyAvatarDisplay lAvatarOnTrackDisplay = new VgMyAvatarDisplay(mSurfaceView, mTextureLoader, mGeometryManager, true);
                    mBasicAppController.addNavigationPositionDisplay(lAvatarOnTrackDisplay);

                    VgMyAvatarDisplay lAvatarDisplay = new VgMyAvatarDisplay(mSurfaceView, mTextureLoader, mGeometryManager, false);
                    mBasicAppController.addNavigationPositionDisplay(lAvatarDisplay);
                }
            }
        }
    }
    
    // Configure VgMyStackedLayerAndCameraHandler parameters
    // For a list of what parameters are configurable, please see
    // VgMyStackedLayerAndCameraHandler
    public void configureStackedLayerAndCameraHandler()
    {
        if(null != mLayerAndCameraHandler)
        {
            // IMPORTANT
            // These parameters are chosen specifically for the Visioglobe Map Generic sample
            // If developing with a different map bundle then there are two choices:
            // 1/ comment the below configurations.  VgMyStackedLayerAndCameraHandler will
            // automatically calculate values which 'should' work for the map bundle.
            // 2/ change the configurations below to work with the map bundle.
            mLayerAndCameraHandler.setParam(VgMyStackedLayerAndCameraHandler.VgMyConfigurableParam.eLayerMaxSize, 700);
            mLayerAndCameraHandler.setParam(VgMyStackedLayerAndCameraHandler.VgMyConfigurableParam.eLayerDistance, 30);
            mLayerAndCameraHandler.setParam(VgMyStackedLayerAndCameraHandler.VgMyConfigurableParam.eLayerDistanceFromCurrent, 170);
            
            // Force the stack view to update
            mLayerAndCameraHandler.refreshStackView();
        }
    }
    
    public void setupLayerSpinner()
    {
        final VgLayerVector lLayers = mSurfaceView.getApplication().editEngine().editLayerManager().editLayers();
        final int lLayersNb = (int) lLayers.size(); 

        runOnUiThread(new Runnable() 
        {
            public void run() 
            {
                mLayerSpinner.setAdapter(mLayersAdapter);

                // Fill the spinner with available layers
                mLayersAdapter.clear();

                for (int i = 0; i <  lLayersNb ; ++i) 
                {
                    // Add layers in reverse order to match how the layers occur in the visual stack
                    mLayersAdapter.insert(lLayers.get((int)(lLayersNb - i - 1)).getName(), i);
                }
            }
        });
    }
    
    /*
     * @return The storage path where all map config data directories will be located.
     * If storage path is not available, will return an empty String.
     */
    public String getPathStorage()
    {
        String lPathStorage = "";
        File lFile = this.getExternalFilesDir(null);
        if(null != lFile)
        {
            lPathStorage = lFile.toString();
        }
        return lPathStorage;
    }
    
    /*
     * @return A path where files can be stored temporarily.  If temporary path
     * is not available, will return an empty String.
     */
    public String getPathTemp()
    {
        String lPathTemp = "";
        File lFile = this.getExternalCacheDir();
        if(null != lFile)
        {
            lPathTemp = lFile.toString();
        }

        return lPathTemp;
    }
    
    /********************************************************
     * @implements VgMySurfaceViewListener
     * 
     */ 
    
    public void onSurfaceChanged(GL10 gl, int pWidth, int pHeight)
    {
        if(null != mLayerAndCameraHandler)
        {
            mLayerAndCameraHandler.refreshParameters(pWidth, pHeight);
        }
        configureStackedLayerAndCameraHandler();
    }
    
    public void onSurfaceDestroyed()
    {}
    
    /********************************************************
     * @implements VgMyLayerAndCameraListener
     * 
     */ 
    
    public void layerWillChangeFrom(VgMyLayerAndCameraHandler pSender, String pLayerFrom, final String pLayerTo)
    {
        // Note: Accessing of UI elements should be performed within the UI thread.
        runOnUiThread(new Runnable() 
        {
            public void run() 
            {
                // Update the floor spinner object to reflect the correct floor name.
                if (pLayerTo.equals(mLayerSpinner.getSelectedItem()) == false ) 
                {
                    if (mLayersAdapter != null) 
                    {
                        // Update the layer spinner, but ignore the event as it's driven by the map and 
                        // not the spinner element
                        if (mLayerSpinnerListener != null)
                        {
                            mLayerSpinnerListener.mIgnoreNextEvent = true;
                        }
                        int spinnerPosition = mLayersAdapter.getPosition(pLayerTo);                     
                        mLayerSpinner.setSelection(spinnerPosition);
                    }
                }
            }
        });
    }
    
    public void layerChangedTo(VgMyLayerAndCameraHandler pSender, String pFloorFrom, String pFloorTo)
    {
        //Log.i("Vg", "layerChangedTo -> implement this method if desired.");
    }
    
    public void viewWillChange(VgMyLayerAndCameraHandler pSender, final boolean pDoesChangeFromGlobalToDetailed)
    {
        runOnUiThread(new Runnable() {
            
            public void run()
            {
                if (pDoesChangeFromGlobalToDetailed)
                {
                    // Enable
                    mSwitchViewButton.setEnabled(true);
                    mSwitchViewButton.setVisibility(View.VISIBLE);
                    
                }
                else
                {
                    // Disable
                    mSwitchViewButton.setEnabled(false);
                    mSwitchViewButton.setVisibility(View.GONE);
                }
            }
        });
        
    }
    
    public void viewDidChange(VgMyLayerAndCameraHandler pSender, boolean pDoesChangeFromGlobalToDetailed)
    {
        //Log.i("Vg", "viewDidChange -> implement this method if desired.");
    }

    @Override
    protected void onDestroy()
    {
        if (mBasicAppController != null)
        {
            mBasicAppController.release();
            mBasicAppController = null;
        }
        
        if (mTextureLoader!= null)
        {
            mTextureLoader.release();
            mTextureLoader = null;
        }
        
        if (mGeometryManager!= null)
        {
            mGeometryManager.release();
            mGeometryManager = null;
        }
        
        if (mLayerAndCameraHandler != null)
        {
            mLayerAndCameraHandler.release();
            mLayerAndCameraHandler = null;
        }
        
        if (mVgMyRemoteMapManager != null)
        {
            mVgMyRemoteMapManager.release();
            mVgMyRemoteMapManager = null;
        }
        
        // remove the surface from the layout
        mSurfaceView.getApplication().editEngine().editDatabase().unloadConfiguration();
        ((ViewGroup)mSurfaceView.getParent()).removeView(mSurfaceView);
        mSurfaceView = null;
        mSwitchViewButton = null;
        
        mConfigPreferences = null;
        
        super.onDestroy();
    }
    
}

./Common/Makefiles/Android/src/com/visioglobe/VisioSample/Blocks/VgMyAvatarDisplay.java

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

package com.visioglobe.VisioSample.Blocks;

import com.visioglobe.VisioSample.R;
import com.visioglobe.VisioSample.VgMyGeometryManager;
import com.visioglobe.VisioSample.VgMySurfaceView;
import com.visioglobe.VisioSample.VgMyTextureLoader;
import com.visioglobe.VisioSample.Interfaces.VgMyNavigationPositionDisplay;
import com.visioglobe.libVisioDevKit.VgAnchorMode;
import com.visioglobe.libVisioDevKit.VgAnimationChannels;
import com.visioglobe.libVisioDevKit.VgAnimationConstRefPtr;
import com.visioglobe.libVisioDevKit.VgAnimationDescriptor;
import com.visioglobe.libVisioDevKit.VgAnimationDescriptorRefPtr;
import com.visioglobe.libVisioDevKit.VgAnimationRefPtr;
import com.visioglobe.libVisioDevKit.VgFunctorDescriptorRefPtr;
import com.visioglobe.libVisioDevKit.VgIAnimationCallbackRefPtr;
import com.visioglobe.libVisioDevKit.VgIGeometryCallbackRefPtr;
import com.visioglobe.libVisioDevKit.VgIMapModule;
import com.visioglobe.libVisioDevKit.VgIModule;
import com.visioglobe.libVisioDevKit.VgIModuleManager;
import com.visioglobe.libVisioDevKit.VgINavigationConstRefPtr;
import com.visioglobe.libVisioDevKit.VgLoopModes;
import com.visioglobe.libVisioDevKit.VgPointDescriptor;
import com.visioglobe.libVisioDevKit.VgPointDescriptorRefPtr;
import com.visioglobe.libVisioDevKit.VgPosition;
import com.visioglobe.libVisioDevKit.VgSinusoidalVectorOffsetFunctorDescriptor;
import com.visioglobe.libVisioDevKit.VgSinusoidalVectorOffsetFunctorDescriptorRefPtr;
import com.visioglobe.libVisioDevKit.VgVectorInterpolationFunctorDescriptor;
import com.visioglobe.libVisioDevKit.VgVectorInterpolationFunctorDescriptorRefPtr;
import com.visioglobe.libVisioDevKit.libVisioDevKit;

public class VgMyAvatarDisplay implements VgMyNavigationPositionDisplay 
{
    private static final String cmAvatarObjects = "avatarObjects";
    private VgMySurfaceView mSurfaceView;
    private VgMyTextureLoader mTextureLoader;
    private VgMyGeometryManager mGeometryManager;
    private String mLayerName = null;
    private boolean mIsAvatarVisible;
    private boolean mProjectOnTrack;
    private VgMyGeometryManager.PointObject mAvatar;

    private final float cGeometryConstantSizeDistance = 100.0f;
    private final float cVisibilityRampStartVisible = 1.0f;
    private final float cVisibilityRampFullyVisible = 5.0f;
    private final float cVisibilityRampStartInvisible = 900.0f;
    private final float cVisibilityRampFullyInvisible = 1000.0f;
    
    private VgPosition mPosition;
    private VgSinusoidalVectorOffsetFunctorDescriptorRefPtr mSinusoidalFuncDescr = null;

    public VgMyAvatarDisplay(VgMySurfaceView pSurfaceView, VgMyTextureLoader pTextureLoader, VgMyGeometryManager pGeometryManager, boolean pProjectOnTrack)
    {
        mSurfaceView = pSurfaceView;
        mTextureLoader = pTextureLoader;
        mGeometryManager = pGeometryManager;
        mProjectOnTrack = pProjectOnTrack;
        loadTextures();

    }

    protected void loadTextures()
    {
        if(null != mTextureLoader)
        {
            if(!mTextureLoader.isImageSet("avatar"))
            {
                mTextureLoader.setImage("avatar", R.drawable.avatar);
            }

            if (!mTextureLoader.isMarkerSet("avatar"))
            {
                mTextureLoader.setMarker("avatar", "avatar");
            }
        }
    }
    
    // Creates a scale animation
    protected VgAnimationRefPtr getAvatarAnimationDescriptor() 
    {
        // Set up a small animation to emphasize the point.
        VgAnimationDescriptorRefPtr lAnimDescr = VgAnimationDescriptor.create();
        lAnimDescr.setMDuration((float) 1.0);
        lAnimDescr.setMCallback(VgIAnimationCallbackRefPtr.getNull());
        lAnimDescr.setMLoopMode(VgLoopModes.getMscLoop());
        
        VgFunctorDescriptorRefPtr lPosFuncDesc = getSinusoidalFuncDesc();
        lAnimDescr.getMFunctorDescriptors().set(VgAnimationChannels.getMscLocalScaleChannel(), lPosFuncDesc);
       
        VgAnimationRefPtr lAnimation = mSurfaceView.getApplication().editEngine().editInstanceFactory().instantiate(lAnimDescr);
        return lAnimation;
    }
    
    // Creates a sinusoidal description
    protected VgFunctorDescriptorRefPtr getSinusoidalFuncDesc ()
    {
        if (null == mSinusoidalFuncDescr)
        {
            VgSinusoidalVectorOffsetFunctorDescriptorRefPtr lSinusoidalFuncDesc = VgSinusoidalVectorOffsetFunctorDescriptor.create();
            lSinusoidalFuncDesc.setMStartPhase(- Math.PI);
            lSinusoidalFuncDesc.setMEndPhase(Math.PI);
            
            float[] lBaseVector = new float[3];
            lBaseVector[0] = 1.0f;
            lBaseVector[1] = 1.0f;
            lBaseVector[2] = 1.0f;
            lSinusoidalFuncDesc.setMBaseVector(lBaseVector);
            
            float[] lVector = new float[3];
            lVector[0] = 0.1f;
            lVector[1] = 0.1f;
            lVector[2] = 0.1f;
            lSinusoidalFuncDesc.setMVector(lVector);
        
            mSinusoidalFuncDescr = lSinusoidalFuncDesc;
        }
        return new VgFunctorDescriptorRefPtr(mSinusoidalFuncDescr.get());
    }

    public void updateWithPosition(VgINavigationConstRefPtr pNavigation, VgPosition pPosition)
    {
        
        // IMPORTANT: Determine which position to use.
        // If the instance of this class is instantiated with the Project on track
        // functionality enabled, then the pPosition argument of this method is ignored and 
        // the closest position on route is used instead.
        if (mProjectOnTrack)
        {
            if (pNavigation.isValid())
            {
                mPosition = pNavigation.getClosestPositionOnRoute();
            }
            else
            {
                // We don't have the navigation.
                return;
            }
        }
        else
        {
            mPosition = new VgPosition(pPosition);
        }

        // Get the layer name associated with the position.
        // NOTE: The layer is associated with a position based on the position's altitude.
        VgIModuleManager lModuleManager = mSurfaceView.getApplication().editModuleManager();
        if (null != lModuleManager) 
        {
            VgIModule lModule = lModuleManager.queryModule("Map");
            if(null != lModule)
            {
                VgIMapModule lMapModule = libVisioDevKit.castToIMapModule(lModule);
                String[] lLayerName = new String[1];
                lMapModule.getLayerForPosition(mPosition, lLayerName);
                mLayerName = lLayerName[0];
            }
        }
        
        VgPosition lPointAvatarPosition = new VgPosition(mPosition);
        // Now that we have the associated layer we can update the altitude 
        // value to be the distance offset from the layers surface.
        lPointAvatarPosition.setMZOrAltitude(5.0);

        // If it doesn't exist, then create the avatar point object
        if(mAvatar == null)
        {
            VgPointDescriptorRefPtr lAvatarDesc = VgPointDescriptor.create();
            lAvatarDesc.setMVisibilityRampStartVisible(cVisibilityRampStartVisible);
            lAvatarDesc.setMVisibilityRampFullyVisible(cVisibilityRampFullyVisible);
            lAvatarDesc.setMVisibilityRampStartInvisible(cVisibilityRampStartInvisible);
            lAvatarDesc.setMVisibilityRampFullyInvisible(cVisibilityRampFullyInvisible);
            lAvatarDesc.setMGeometryConstantSizeDistance(cGeometryConstantSizeDistance);
            lAvatarDesc.setMAnchorPosition(VgAnchorMode.eVgBottomCenter);
            lAvatarDesc.setMPosition(lPointAvatarPosition);
            lAvatarDesc.setMDrawOnTop(true);
            lAvatarDesc.getMMarkerDescriptors().add(mTextureLoader.getMarker("avatar"));
            mAvatar = mGeometryManager.createPointObject(cmAvatarObjects, mLayerName, lAvatarDesc,  VgIGeometryCallbackRefPtr.getNull());
            
            if (null != mAvatar.mPoint)
            {
                VgAnimationRefPtr lAnimation = getAvatarAnimationDescriptor();
                mAvatar.mPoint.setAnimation("",lAnimation);
                lAnimation.start();
            }           
        }
        // If it already exists, then just need to update it's parameters to reflect any changes.
        else
        {
            mAvatar.setLayerName(mLayerName);
            
            VgPosition lStartPosition = mAvatar.mPoint.getPosition();
            VgPosition lEndPosition = lPointAvatarPosition;
            double lDistance = mSurfaceView.getApplication().editEngine().getPositionToolbox().computeDistance(lStartPosition, lEndPosition);
            
            if (lDistance < 0.1)
            {
                // Non-animated version
                mAvatar.mPoint.setPosition(lPointAvatarPosition);
            }
            else
            {
                VgAnimationConstRefPtr lAnimation = mAvatar.mPoint.getAnimation("positionAnim");
                // Animated version
                if ( (false == lAnimation.isValid() ) || 
                        (false == lAnimation.isPlaying()) )
                {
                    VgAnimationDescriptorRefPtr lAnimDescr = VgAnimationDescriptor.create();
                    VgVectorInterpolationFunctorDescriptorRefPtr lFuncDescr = VgVectorInterpolationFunctorDescriptor.create();
                    
                    lFuncDescr.setMStartTime(0.0f);
                    lFuncDescr.setMStartPosition(lStartPosition);
                    lFuncDescr.setMEndPosition(lEndPosition);

                    float lAnimationDuration = (float) (Math.log(lDistance+1) * 0.05f);
                    lFuncDescr.setMEndTime( lAnimationDuration );
                    lFuncDescr.setMCubic(false);

                    lAnimDescr.getMFunctorDescriptors().set(VgAnimationChannels.getMscPositionChannel(), new VgFunctorDescriptorRefPtr(lFuncDescr.get()));
                    lAnimDescr.setMDuration( lAnimationDuration );
                    
                    VgAnimationRefPtr lAnim = mSurfaceView.getApplication().editEngine().editInstanceFactory().instantiate(lAnimDescr);
                    mAvatar.mPoint.setAnimation("positionAnim", lAnim);
                    lAnim.start();
                }
            }
        }

        // Add the object
        if (mIsAvatarVisible)
        {
            mGeometryManager.addObjects(cmAvatarObjects);
        }
    }
    
    
    public void clear()
    {
        hide();

        mGeometryManager.deleteObjects(cmAvatarObjects);
        // Set to null so the object will be re-created and re-added to VgMyGeometryManager
        mAvatar = null;
    }

    public void show()
    {
        mIsAvatarVisible = true;

        if (mAvatar != null)
        {
            mGeometryManager.addObjects(cmAvatarObjects);
        }
    }

    public void hide()
    {
        mIsAvatarVisible = false;
        
        mGeometryManager.removeObjects(cmAvatarObjects);
    }

    public boolean isVisible()
    {
        return mIsAvatarVisible;        
    }
    
    public void release() 
    {
        mSurfaceView = null;
        mTextureLoader = null;
        mGeometryManager = null;
        mAvatar = null;
        mPosition = null;
        mSinusoidalFuncDescr = null;
    }

}

./Common/Makefiles/Android/src/com/visioglobe/VisioSample/Blocks/VgMyBubbleView.java

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

package com.visioglobe.VisioSample.Blocks;

import android.app.Activity;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.FrameLayout.LayoutParams;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.visioglobe.VisioSample.R;
import com.visioglobe.VisioSample.VgMySurfaceView;
import com.visioglobe.VisioSample.Interfaces.VgMyAnchoredDisplay;
import com.visioglobe.VisioSample.Interfaces.VgMyLayerAndCameraHandler;
import com.visioglobe.VisioSample.Interfaces.VgMyLayerAndCameraListener;
import com.visioglobe.VisioSample.Interfaces.VgMyRouteCreator;
import com.visioglobe.VisioSample.Interfaces.VgMyRouteCreator.RoutePoint;
import com.visioglobe.libVisioDevKit.VgIApplication;
import com.visioglobe.libVisioDevKit.VgIEngineContext;
import com.visioglobe.libVisioDevKit.VgIEnginePostDrawCallback;
import com.visioglobe.libVisioDevKit.VgIEnginePostDrawCallbackRefPtr;
import com.visioglobe.libVisioDevKit.VgIMapModule;
import com.visioglobe.libVisioDevKit.VgIModule;
import com.visioglobe.libVisioDevKit.VgIModuleManager;
import com.visioglobe.libVisioDevKit.VgIPlaceListener;
import com.visioglobe.libVisioDevKit.VgIPlaceListenerRefPtr;
import com.visioglobe.libVisioDevKit.VgPlaceDescriptor;
import com.visioglobe.libVisioDevKit.VgPosition;
import com.visioglobe.libVisioDevKit.libVisioDevKit;

public class VgMyBubbleView 
    implements 
        VgMyAnchoredDisplay,
        VgMyLayerAndCameraListener
{
    protected class ViewRepositionPostDrawCallback extends VgIEnginePostDrawCallback
    {
        public ViewRepositionPostDrawCallback(VgPosition pPosition) 
        {
            // Mandatory call for classes inheriting from SDK's objects (dependency of the SWIG/Director bridge)
            super();
            // The position must be allocated here. 
            // Once outside this scope, the native object will be freed and the pPosition object will hold garbage.  
            mPositionPrivate = new VgPosition(pPosition);
        }

        @Override
        public void postDraw(VgIEngineContext pContext) 
        {
            
            // Projects the stored position on the screen frame and update the bubble layout to stick to it
            double[] lX = { 0.0 }, lY = { 0.0 }, lZ = { 0.0 };
            mApplication.editEngine().editCamera().projectOnScreen(mPositionPrivate, lX, lY, lZ);
            
            if (lX[0] < 0f) {
                lX[0] = 0f;
            }
            if (lX[0] > 1.0f) {
                lX[0] = 1.0f;
            }
            if (lY[0] < 0f) {
                lY[0] = 0f;
            }
            if (lY[0] > 1.0f) {
                lY[0] = 1.0f;
            }
            
            final float lCenterx = (float) lX[0];
            final float lCentery = (float) lY[0];

            mActivity.runOnUiThread(new Runnable() 
            {
                public void run() 
                {
                    if(null != mBubbleView)
                    {
                        mBubbleView.setVisibility(View.VISIBLE);
                        // Reminder: The Framelayout refers to the parent of the bubble view
                        FrameLayout.LayoutParams lLayoutParam = (LayoutParams) mBubbleView.getLayoutParams();

                        lLayoutParam.leftMargin = (int) (lCenterx * mSurfaceViewGroup.getWidth() - mBubbleView.getWidth() / 2.0f);
                        lLayoutParam.topMargin = (int) ((1.0f - lCentery) * mSurfaceViewGroup.getHeight() - mBubbleView.getHeight());
                        
                        
                        
                        mSurfaceViewGroup.updateViewLayout(mBubbleView, lLayoutParam);
                    }
                }
            });
        }

        private VgPosition mPositionPrivate;
    }
    
    
    class VgMyPlaceListener extends VgIPlaceListener
    {
        public VgMyPlaceListener() 
        {
            super();
        }

        @Override
        public void notifyPlaceSelected(final VgIApplication pApplication, final String pPlaceId, final VgPosition pPosition) 
        {
            // Notify VgMyAnchoredDisplay interface
            setAnchorPosition(pPlaceId, pPosition);
            show();
        }
    }
    
    protected LinearLayout mBubbleView = null;                  
    protected Activity mActivity = null;
    protected VgMyRouteCreator mRouteCreator = null;
    protected VgIApplication mApplication = null;
    protected VgIMapModule mMapModule = null;
    protected VgIEnginePostDrawCallbackRefPtr mPostDrawCallback = null;
    protected VgMySurfaceView mSurfaceView = null;
    protected VgPosition mPosition = null;                      
    protected String mCurrentAnchoredLayer = null;
    protected String mPlaceId = null;
    protected ViewGroup mSurfaceViewGroup;
    protected VgIPlaceListenerRefPtr mPlaceListener;
    
    public VgMyBubbleView(Activity pActivity, VgMyRouteCreator pRouteCreator, VgMySurfaceView pSurfaceView, ViewGroup pViewGroup)
    {
        mRouteCreator = pRouteCreator;
        mSurfaceView = pSurfaceView;
        mActivity = pActivity;
        mSurfaceViewGroup = pViewGroup;
        
        mApplication = mSurfaceView.getApplication();
        
        
        mMapModule = libVisioDevKit.castToIMapModule(mApplication.editModuleManager().queryModule("Map"));
        mPlaceListener = new VgIPlaceListenerRefPtr(new VgMyPlaceListener());
    }

    protected void updateBubbleView(final String pPlaceID) 
    { 
        // Important: Perform all UI related tasks within the UI thread.
        mActivity.runOnUiThread(new Runnable() 
        {
            public void run() 
            { 
                // Create the bubble view if not already created
                if (mBubbleView == null) 
                {
                    mBubbleView = (LinearLayout)mActivity.getLayoutInflater().inflate(R.layout.bubbleview, null);

                    // Register Close listener
                    ImageButton lImageClose = (ImageButton) mBubbleView.findViewById(R.id.imageViewClose);
                    lImageClose.setOnClickListener(new OnClickListener() 
                    {
                        public void onClick(View v) 
                        {
                            mSurfaceView.queueEvent(new Runnable() 
                            {
                                public void run() 
                                {
                                    hide();
                                }
                            });
                        }
                    });

                    // Register Go listener
                    ImageButton lImageGo = (ImageButton) mBubbleView.findViewById(R.id.imageViewGo);
                    lImageGo.setOnClickListener(new OnClickListener() 
                    {
                        public void onClick(View v) 
                        {
                            TextView lText = (TextView) mBubbleView.findViewById(R.id.textViewBubble);
                            Toast.makeText(mActivity.getBaseContext(), mActivity.getResources().getString(R.string.messagePlaceClicked) + lText.getText(), Toast.LENGTH_SHORT).show();
                        }
                    });

                    // Register Route To listener
                    Button lRouteTo = (Button) mBubbleView.findViewById(R.id.buttonRouteTo);
                    lRouteTo.setOnClickListener(new OnClickListener() 
                    {
                        public void onClick(View v) 
                        {
                            mSurfaceView.queueEvent(new Runnable() 
                            {
                                public void run() 
                                {
                                    // Connect the route creator to the bubble.
                                    if(null != mRouteCreator)
                                    {
                                        mRouteCreator.setRoutePoint(RoutePoint.eEnd, mPlaceId);
                                    }

                                    hide();
                                }
                            });
                        }
                    });

                    // Register Route From listener
                    Button lRouteFrom = (Button) mBubbleView.findViewById(R.id.buttonRouteFrom);
                    lRouteFrom.setOnClickListener(new OnClickListener() 
                    {
                        public void onClick(View v) 
                        {
                            mSurfaceView.queueEvent(new Runnable() 
                            {
                                public void run() 
                                {
                                    // Connect the route creator to the bubble.
                                    if (null != mRouteCreator) 
                                    {
                                        mRouteCreator.setRoutePoint(RoutePoint.eStart, mPlaceId);
                                    }

                                    hide();
                                }
                            });
                        }
                    });

                    mBubbleView.setVisibility(View.GONE); // Wait for the post draw callback to trigger to display it
                                        
                    Button lSetRouteFrom = (Button) mBubbleView.findViewById(R.id.buttonRouteFrom);
                    Button lSetRouteTo = (Button) mBubbleView.findViewById(R.id.buttonRouteTo);
                    
                    lSetRouteFrom.setEnabled(false);
                    lSetRouteTo.setEnabled(false);
                            
                    // Only enable the routing buttons if the routing module is enabled 
                    VgIModuleManager lModuleManager = mSurfaceView.getApplication().editModuleManager();
                    if (null != lModuleManager) 
                    {
                        VgIModule lRoutingModule = lModuleManager.queryModule("Routing");
                        if(null != lRoutingModule)
                        {
                            // Routing is enabled, enable the routing buttons.
                            lSetRouteFrom.setEnabled(true);
                            lSetRouteTo.setEnabled(true);
                        }
                    }
                    
                    // Take into account the screens with different pixel densities.
                    int lPixelWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 250, mActivity.getResources().getDisplayMetrics());
                    
                    // Determine size of bubble view here (not within the layout)
                    FrameLayout.LayoutParams lLayoutParam = new FrameLayout.LayoutParams(
                            lPixelWidth,
                            android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
                            Gravity.LEFT | Gravity.TOP);

                    mSurfaceViewGroup.addView(mBubbleView, lLayoutParam);
                } // if (mBubbleView == null)

                // Display the place id as the bubble title
                // This code can be extended so the place name is used as the title
                // rather then the place id. 
                TextView lText = (TextView) mBubbleView.findViewById(R.id.textViewBubble);
                lText.setText(pPlaceID);
            }
        });

    }
    
    

    /**********************************************************************************************************
     * @implements VgMyAnchoredDisplay
     */
    
    public void setAnchorPosition(String pPlaceId, VgPosition pPosition) 
    {
        mPlaceId = pPlaceId;
        mPosition = new VgPosition(pPosition);

        VgPlaceDescriptor lPlaceDesc = new VgPlaceDescriptor();
        mMapModule.queryPlaceDescriptor(pPlaceId, lPlaceDesc);
        
        mCurrentAnchoredLayer = lPlaceDesc.getMLayerName();

        updateBubbleView(mPlaceId);

        if(null != mPostDrawCallback)
        {
            if (mPostDrawCallback.isValid())
            {
                mApplication.editEngine().removePostDrawCallback(mPostDrawCallback);
                mPostDrawCallback.set(null);
            }
            mPostDrawCallback = null;
        }

        // Create the post draw callback associated with this position. 
        mPostDrawCallback = new VgIEnginePostDrawCallbackRefPtr( new ViewRepositionPostDrawCallback(mPosition) );
    }

    /*******************************************************************************************
     * @implements VgMyDisplayable
     */
    
    
    public void show()
    {
        if (null != mPostDrawCallback) 
        {
            // Register the post draw callback that will update the bubble to stick to the clicked position 
            mApplication.editEngine().addPostDrawCallback(mPostDrawCallback);
        }

        // Note: mBubbleView.setVisibility(View.VISIBLE); will be called within the postDraw event of the 
        // mPostDrawCallback object, because it's there where the correct on screen location for the bubble view
        // is calculated and we don't want to display the bubble view before we that location.
    }

    public void hide()
    {
        if (mBubbleView != null) 
        {
            if(null != mPostDrawCallback)
            {
                mApplication.editEngine().removePostDrawCallback(mPostDrawCallback);
            }

            // Important: Invisibility of the bubble view must be set AFTER the post draw callback 
            // has been removed otherwise the post draw method will cause the bubble view to reappear.
            mActivity.runOnUiThread(new Runnable() 
            {
                public void run() 
                { 
                    mBubbleView.setVisibility(View.GONE);
                }
            });
        }
    }

    public boolean isVisible()
    {
        if(null != mBubbleView)
        {
            return (View.VISIBLE == mBubbleView.getVisibility());
        }
        return false;
    }
    
    
    public void layerWillChangeFrom(VgMyLayerAndCameraHandler pSender, String pFloorFrom, String pFloorTo)
    {
        if (false == pSender.isGlobalView())
        {
            hide();   // No matter the transition, in detailed view mode, the bubble is hidden.
        }
    }

    public void layerChangedTo(VgMyLayerAndCameraHandler pSender, String pFloorFrom, String pFloorTo)
    {
        if (false == pSender.isGlobalView() )
        {
            hide();   // No matter the transition, in detailed view mode, the bubble is hidden.
        }
    }

    public void viewWillChange(VgMyLayerAndCameraHandler pSender, boolean pDoesChangeFromGlobalToDetailed)
    {
        if ((null != mCurrentAnchoredLayer) &&
                (true == pDoesChangeFromGlobalToDetailed) && 
                (false == mCurrentAnchoredLayer.contentEquals( pSender.getFocusedLayerName() )) )
        {
            hide();
        }
        
        // Leaving detailed view
        if (false == pDoesChangeFromGlobalToDetailed)
        {
            mMapModule.removeListener(mPlaceListener);
        }
    }
    
    public void viewDidChange(VgMyLayerAndCameraHandler pSender, boolean pDoesChangeFromGlobalToDetailed)
    {
        // arriving at detailed view
        if (true == pDoesChangeFromGlobalToDetailed)
        {
            mMapModule.addListener(mPlaceListener);
        }
    }

    @Override
    public void release() {
        if(mPostDrawCallback != null)
        {
            mApplication.editEngine().removePostDrawCallback(mPostDrawCallback);
        }
        mPostDrawCallback = null;
        if (mMapModule != null)
        {
            if (mPlaceListener != null)
            {
                if (mPlaceListener.isValid())
                {
                    mMapModule.removeListener(mPlaceListener);
                    mPlaceListener.set(null);
                }
                mPlaceListener = null;
            }
            mMapModule = null;
        }
        mActivity = null;
        mRouteCreator = null;
        mApplication = null;
        mPosition = null;
        mSurfaceViewGroup = null;
        mSurfaceView = null;
        mBubbleView = null;
    }
}

./Common/Makefiles/Android/src/com/visioglobe/VisioSample/Blocks/VgMyInstructionPathDisplay.java

./Common/Makefiles/Android/src/com/visioglobe/VisioSample/Blocks/VgMyNavigationHelper.java

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */
package com.visioglobe.VisioSample.Blocks;

import android.app.Activity;

import com.visioglobe.VisioSample.Interfaces.VgMyNavigationCreator;
import com.visioglobe.libVisioDevKit.VgIMapModule;
import com.visioglobe.libVisioDevKit.VgIModule;
import com.visioglobe.libVisioDevKit.VgIModuleManager;
import com.visioglobe.libVisioDevKit.VgINavigationConstRefPtr;
import com.visioglobe.libVisioDevKit.VgINavigationInstructionConstRefPtr;
import com.visioglobe.libVisioDevKit.VgINavigationModule;
import com.visioglobe.libVisioDevKit.VgINavigationRequestParameters;
import com.visioglobe.libVisioDevKit.VgManeuverType;
import com.visioglobe.libVisioDevKit.VgNearPlaceVector;
import com.visioglobe.libVisioDevKit.VgSurfaceView;
import com.visioglobe.libVisioDevKit.libVisioDevKit;

public class VgMyNavigationHelper implements VgMyNavigationCreator 
{
    enum StringType
    {
        eStringFor,
        eStringThen,
        eStringAnd,
        eStringNear,
        eStringUsing,
        eStringCount,
    };
    
    
    /**********************************************************************************************************
     * Static methods associated with languages
     */

    
    final static protected String[] cLanguageStrings = { "en", "fr"};
    
    
    final static protected int cNumLanguages = cLanguageStrings.length;
    

    final static protected String cActionStringTable[][] = // [cNumLanguages][VgManeuverType.eVgManeuverTypeMax.swigValue()]
    {
        {
            "<unknown>", // eVgManeuverTypeUnknown
            "Go straight",
            "Turn gentle right",
            "Turn gentle left",
            "Turn right",
            "Turn left",
            "Turn sharp right",
            "Turn sharp left",
            "Make right U-turn",
            "Make left U-turn",
            "Start",
            "You have arrived",
            "Go up to floor %L",
            "Go down to floor %L",
            "Use transportation mode %M",
        },
        {
            "<inconnu>", // eVgManeuverTypeUnknown
            "Continuez tout droit",
            "Tournez légèrement à droite",
            "Tournez légèrement à gauche",
            "Tournez à droite",
            "Tournez à gauche",
            "Tournez fortement à droite",
            "Tournez fortement à gauche",
            "Effectuez un demi-tour à droite",
            "Effectuez un demi-tour à gauche",
            "Départ",
            "Arrivée",
            "Montez à l'étage %L",
            "Descendez à l'étage %L",
            "Changez de moyen de transport: %M",
        },
    };

    final static protected String cNextActionStringTable[][] = // [cNumLanguages][VgManeuverType.eVgManeuverTypeMax.swigValue()]
    {
        {
            "<unknown>", // eVgManeuverTypeUnknown
            "go straight",
            "turn gentle right",
            "turn gentle left",
            "turn right",
            "turn left",
            "turn sharp right",
            "turn sharp left",
            "make right U-turn",
            "make left U-turn",
            "start",
            "you have arrived",
            "go up",
            "go down",
            "change transportation mode: %M",
        },
        {
            "<inconnu>", // eVgManeuverTypeUnknown
            "continuez tout droit",
            "tournez légèrement à droite",
            "tournez légèrement à gauche",
            "tournez à droite",
            "tournez à gauche",
            "tournez fortement à droite",
            "tournez fortement à gauche",
            "effectuez un demi-tour à droite",
            "effectuez un demi-tour à gauche",
            "départ",
            "vous serez arrivés",
            "montez",
            "descendez",
            "changez de mode de transport: %M",
        },
    };

    final static protected String cTimeStringTable[][] = // [cNumLanguages][3]
    {
        {
            "a few seconds",
            "about a minute",
            "about %d minutes",
        },
        {
            "quelques secondes",
            "environ une minute",
            "environ %d minutes",
        },
    };
    
    static protected String cStringTable[][] = // [cNumLanguages][StringType.eStringCount.ordinal()]
    {
        {
            " for ",
            " then ",
            " and ",
            " near ",
            " using ",
        },
        {
            " pendant ",
            " puis ",
            " et ",
            " à proximité de ",
            " en empruntant ",
        },
    };

    static class VgTranslatedInstruction
    {
        String mBrief;
        String mMessage;
        String mDuration;
        float mDurationInSeconds;
    };

    static public void translateInstruction(
        VgINavigationInstructionConstRefPtr pInstruction,
        VgINavigationConstRefPtr mNavigation2,
        VgTranslatedInstruction pTranslated,
        VgIMapModule pMapModule,
        int pLang)

        {
            //format:
            //  en: {action}[{duration}][{nextAction}[{means}]].
            //  fr: {action}[{duration}][{nextAction}[{means}]].
            //
            //action:
            //  en: "Change transportation mode"    | "Go up"  | "Go down"   | "Go straight"
            //  fr: "Changez de moyen de transport" | "Montez" | "Descendez" | "Continuez"
            //
            //2:
            //  en: " for a few seconds"     | " for about a minute"     | " for about {dur} minutes" | ""
            //  fr: " pendant quelques secondes" | " pendant environ une minute" | " pendant environ {dur} minutes"
            //
            //3: 
            //  en: " then change transportation mode"    | " go up"  | " go down"   | " go straight"
            //  fr: " puis changez de moyen de transport" | " montez" | " descendez" | " continuez"
            //
            //4:
            //  en: " using {placeName}"         | " near {placeName}"
            //  fr: " en empruntant {placeName}" | " à proximité de {placeName}"
            
            // Strings to compose the message
            String lStringAction = new String();
            String lStringDuration = new String();
            String lStringNextAction = new String();
            String lStringVincinity = new String();;

            // lNextInstr will be invalid if there is no next instruction (i.e. this one is the last)
            VgINavigationInstructionConstRefPtr lNextInstr = mNavigation2.getInstruction(pInstruction.getIndex() + 1);
            
            if ( (pInstruction.getManeuverType().swigValue() == VgManeuverType.eVgManeuverTypeChangeModality.swigValue()) ||
                 (pInstruction.getManeuverType().swigValue() == VgManeuverType.eVgManeuverTypeEnd.swigValue()) ||
                 (pInstruction.getManeuverType().swigValue() == VgManeuverType.eVgManeuverTypeGoDown.swigValue()) ||
                 (pInstruction.getManeuverType().swigValue() == VgManeuverType.eVgManeuverTypeGoUp.swigValue()) ||
                 (pInstruction.getManeuverType().swigValue() == VgManeuverType.eVgManeuverTypeStart.swigValue()) )
            {
                    lStringAction = cActionStringTable[pLang][pInstruction.getManeuverType().swigValue()];
            }
            else if (pInstruction.getManeuverType().swigValue() == VgManeuverType.eVgManeuverTypeGoStraight.swigValue())
            {

                lStringAction = cActionStringTable[pLang][VgManeuverType.eVgManeuverTypeGoStraight.swigValue()];
                lStringDuration = cStringTable[pLang][StringType.eStringFor.ordinal()] + VgMyNavigationHelper.timeToText(pInstruction.getDuration()/60.0f, pLang);
                if (mNavigation2.getRequestParameters().getMMergeFloorChangeInstructions())
                {
                    // When instruction merging is active, we have to test the next
                    // instruction's layer/modality to know if we should instruct to change
                    // level/transportation.
                    if (false == lNextInstr.isValid())
                    {
                        // Last instruction means next action is "you have arrived"
                        lStringNextAction = cStringTable[pLang][StringType.eStringThen.ordinal()] + cNextActionStringTable[pLang][VgManeuverType.eVgManeuverTypeEnd.swigValue()];
                    }
                    else if (lNextInstr.getLayer() != pInstruction.getLayer())
                    {
                        // TODO: Test whether we go up or down
                        lStringNextAction = cStringTable[pLang][StringType.eStringThen.ordinal()] + cNextActionStringTable[pLang][VgManeuverType.eVgManeuverTypeGoUp.swigValue()];
                        if (lNextInstr.getModality() != pInstruction.getModality())
                        {
                            lStringNextAction += cStringTable[pLang][StringType.eStringAnd.ordinal()] + cNextActionStringTable[pLang][VgManeuverType.eVgManeuverTypeChangeModality.swigValue()];
                        }
                    }
                    else if (lNextInstr.getModality() != pInstruction.getModality())
                    {
                        lStringNextAction += cStringTable[pLang][StringType.eStringThen.ordinal()] + cNextActionStringTable[pLang][VgManeuverType.eVgManeuverTypeChangeModality.swigValue()];
                    }
                }
                else
                {
                    // When instruction merging is inactive, we have to test the next
                    // instruction's type to know if we should instruct to change level
                    // or transportation mode.
                    if (pInstruction.getIndex() < mNavigation2.getNumInstructions() - 1)
                    {
                        if (true == lNextInstr.isValid())
                        {
                            if( (lNextInstr.getManeuverType().swigValue() == VgManeuverType.eVgManeuverTypeChangeModality.swigValue()) ||
                                    (lNextInstr.getManeuverType().swigValue() == VgManeuverType.eVgManeuverTypeEnd.swigValue()) ||
                                    (lNextInstr.getManeuverType().swigValue() == VgManeuverType.eVgManeuverTypeGoDown.swigValue()) ||
                                    (lNextInstr.getManeuverType().swigValue() == VgManeuverType.eVgManeuverTypeGoUp.swigValue()) )
                            {
                                lStringNextAction = cStringTable[pLang][StringType.eStringThen.ordinal()] + cNextActionStringTable[pLang][lNextInstr.getManeuverType().swigValue()];
                            }
                        }
                    }
                    else
                    {
                        // We are on last instruction, so no next action.
                    }
                }
            }
            else
            {

                // These are turn left/right instructions
                lStringAction = cActionStringTable[pLang][VgManeuverType.eVgManeuverTypeGoStraight.swigValue()];
                lStringDuration = cStringTable[pLang][StringType.eStringFor.ordinal()] + timeToText(pInstruction.getDuration()/60.0f, pLang);
                lStringNextAction = cStringTable[pLang][StringType.eStringThen.ordinal()] + cNextActionStringTable[pLang][pInstruction.getManeuverType().swigValue()];
            }

            // Use Natural Guidance information
            boolean lSkipNearPlaces = false;
            VgNearPlaceVector lPlaces = pInstruction.getNearPlaces();
            
            if (
                (
                    mNavigation2.getRequestParameters().getMMergeFloorChangeInstructions()
                    && pInstruction.getIndex() >= mNavigation2.getNumInstructions() - 1
                )
                || (
                    !mNavigation2.getRequestParameters().getMMergeFloorChangeInstructions()
                    && pInstruction.getIndex() >= mNavigation2.getNumInstructions() - 2
                )
            )
            {
                lSkipNearPlaces = true;
            }

            // Handle the case where the next instruction is a floor change, we want to use "using" escalator
            // and not near escalator.
            boolean lThereIsFloorChange = false;
            if (!mNavigation2.getRequestParameters().getMMergeFloorChangeInstructions()
                && pInstruction.getIndex() < (mNavigation2.getNumInstructions() - 2)
                && mNavigation2.getInstruction(pInstruction.getIndex()+1).isEndOrTransitionPoint())
            {
                lThereIsFloorChange = true; 
            }

            if (!lSkipNearPlaces &&
                (null != pMapModule) )
            {
                if (lPlaces.size() > 0)
                {
                    String[] lPlaceNameTemp = new String[1];
                    pMapModule.getPlaceName(lPlaces.get(0).getMID(), lPlaceNameTemp);
                    String lPlaceName = lPlaceNameTemp[0];
                    if (0 != lPlaceName.length())
                    {
                        if (lThereIsFloorChange)
                        {
                            if (lPlaceName.contains("Escalator") == true ||
                                lPlaceName.contains("Elevator") == true ||
                                lPlaceName.contains("Lifts") == true)
                            {
                                // we say using, if the near POI is a [E]scalator or [E]levator.
                                // else we say nothing.
                                lStringVincinity = cStringTable[pLang][StringType.eStringUsing.ordinal()] + lPlaceName;
                            }
                        }
                        else 
                        {
                            lStringVincinity = cStringTable[pLang][StringType.eStringNear.ordinal()] + lPlaceName;
                        }
                    }
                    // else maybe choose another shop?
                }
            }

            pTranslated.mMessage = replaceTokens(lStringAction + lStringDuration + lStringNextAction + lStringVincinity, pInstruction, lNextInstr);
            pTranslated.mBrief = replaceTokens(lStringAction, pInstruction, lNextInstr);
            pTranslated.mDuration = replaceTokens(lStringDuration, pInstruction, lNextInstr);
            pTranslated.mDurationInSeconds = pInstruction.getDuration();
    }
    
    protected static String replaceTokens(String pStringWithTokens, VgINavigationInstructionConstRefPtr pInstruction, VgINavigationInstructionConstRefPtr lNextInstr)
    {
        //String lResult = new String(pStringWithTokens);
        // Replaces occurrences of a token with contextual data
        if(pInstruction.isValid())
        {
            // Replace duration field (%d)
            int lDurationInMintues = (int) (pInstruction.getDuration() / 60.0f);
            pStringWithTokens = pStringWithTokens.replace("%d", String.valueOf(lDurationInMintues));
            // Replace modality field (%m)
            pStringWithTokens = pStringWithTokens.replace("%m", pInstruction.getModality());
            // Replace layer field (%l)
            pStringWithTokens = pStringWithTokens.replace("%l", pInstruction.getLayer());
        }
        
        if (lNextInstr.isValid())
        {
            // Replace the next modality field (%M)
            pStringWithTokens = pStringWithTokens.replace("%M", lNextInstr.getModality());
            // Replace the next Layer field (%L)
            pStringWithTokens = pStringWithTokens.replace("%L", lNextInstr.getLayer());
        }
        return pStringWithTokens;
    }   

    static int getLangId (String pLangSr)
    {
        if (pLangSr.length() < 2)
        {
            return 0;
        }
        // Extract and use just the first two letters.
        String lLang2 = pLangSr.substring(0, 2);
        for (int i = 0; i < cNumLanguages; ++i)
        {
            if (true == cLanguageStrings[i].equalsIgnoreCase(lLang2))
            {
                return i;
            }
        }
        return 0;
    }

    static String timeToText (float pTimeInMinutes, int pLang)
    {
        if(pLang >= cNumLanguages)
        {
            pLang = 0;
        }
         
        if (pTimeInMinutes < 1.0)
        {
            return cTimeStringTable[pLang][0];
        }
        else if (pTimeInMinutes < 2.0)
        {
            return cTimeStringTable[pLang][1];
        }
        else
        {
            return cTimeStringTable[pLang][2];
        }
    }

    
    private VgSurfaceView mSurfaceView;


    public VgMyNavigationHelper(Activity pActivity, VgSurfaceView pSurfaceView)
    {
        mSurfaceView  = pSurfaceView;
    }


    /**********************************************************************************************************
     * @implements VgMyNavigationCreator
     */

    public void createNavigation(final VgINavigationRequestParameters pParameters)
    {

        VgIModuleManager lModuleManager = mSurfaceView.getApplication().editModuleManager();

        if (null != lModuleManager) 
        {
            VgIModule lModule = lModuleManager.queryModule("Navigation");
            if(null != lModule)
            {
                VgINavigationModule lNavigationModule = libVisioDevKit.castToINavigationModule(lModule);
                /*VgINavigationRequest lRequest =*/ lNavigationModule.computeNavigation(pParameters);
            }
        }
    }

    @Override
    public void release()
    {
        mSurfaceView = null;
    }


}

./Common/Makefiles/Android/src/com/visioglobe/VisioSample/Blocks/VgMyRoutingHelper.java

/*
 * Copyright 2013, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 * 
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 * 
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 * 
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 * 
 * Contact information:  Visioglobe SAS, 
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */
package com.visioglobe.VisioSample.Blocks;

import java.util.HashMap;

import android.util.Log;

import com.visioglobe.VisioSample.R;
import com.visioglobe.VisioSample.VgMyGeometryManager;
import com.visioglobe.VisioSample.VgMyGeometryManager.PointObject;
import com.visioglobe.VisioSample.VgMySurfaceView;
import com.visioglobe.VisioSample.VgMyTextureLoader;
import com.visioglobe.VisioSample.Interfaces.VgMyLayerAndCameraHandler;
import com.visioglobe.VisioSample.Interfaces.VgMyPoiConfigurationSetter;
import com.visioglobe.VisioSample.Interfaces.VgMyRouteCreator;
import com.visioglobe.VisioSample.Interfaces.VgMyRouteDisplay;
import com.visioglobe.libVisioDevKit.VgAnchorMode;
import com.visioglobe.libVisioDevKit.VgAnimationChannels;
import com.visioglobe.libVisioDevKit.VgAnimationDescriptor;
import com.visioglobe.libVisioDevKit.VgAnimationDescriptorRefPtr;
import com.visioglobe.libVisioDevKit.VgAnimationRefPtr;
import com.visioglobe.libVisioDevKit.VgAxialRotationQuaternionFunctorDescriptor;
import com.visioglobe.libVisioDevKit.VgAxialRotationQuaternionFunctorDescriptorRefPtr;
import com.visioglobe.libVisioDevKit.VgColor;
import com.visioglobe.libVisioDevKit.VgFunctorDescriptorRefPtr;
import com.visioglobe.libVisioDevKit.VgIAnimationCallbackRefPtr;
import com.visioglobe.libVisioDevKit.VgIApplication;
import com.visioglobe.libVisioDevKit.VgIGeometryCallback;
import com.visioglobe.libVisioDevKit.VgIGeometryCallbackRefPtr;
import com.visioglobe.libVisioDevKit.VgIGeometryEvent;
import com.visioglobe.libVisioDevKit.VgIMapModule;
import com.visioglobe.libVisioDevKit.VgIModule;
import com.visioglobe.libVisioDevKit.VgIModuleManager;
import com.visioglobe.libVisioDevKit.VgIRouteCallbackRefPtr;
import com.visioglobe.libVisioDevKit.VgIRouteConstRefPtr;
import com.visioglobe.libVisioDevKit.VgIRouteConverter;
import com.visioglobe.libVisioDevKit.VgIRouteConverterType;
import com.visioglobe.libVisioDevKit.VgIRouteGeometryDescriptor;
import com.visioglobe.libVisioDevKit.VgIRouteGeometryDescriptorVector;
import com.visioglobe.libVisioDevKit.VgIRouteRequestParameters;
import com.visioglobe.libVisioDevKit.VgIRoutingModule;
import com.visioglobe.libVisioDevKit.VgIRoutingNodeRefPtr;
import com.visioglobe.libVisioDevKit.VgIRoutingNodeRefPtrVector;
import com.visioglobe.libVisioDevKit.VgIRoutingSolver;
import com.visioglobe.libVisioDevKit.VgITextureRefPtr;
import com.visioglobe.libVisioDevKit.VgLineDescriptorRefPtr;
import com.visioglobe.libVisioDevKit.VgLineDescriptorVector;
import com.visioglobe.libVisioDevKit.VgLinkDescriptor;
import com.visioglobe.libVisioDevKit.VgLinkDescriptorRefPtr;
import com.visioglobe.libVisioDevKit.VgLoopModes;
import com.visioglobe.libVisioDevKit.VgMarkerDescriptorRefPtr;
import com.visioglobe.libVisioDevKit.VgMarkerDescriptorVector;
import com.visioglobe.libVisioDevKit.VgPlaceDescriptor;
import com.visioglobe.libVisioDevKit.VgPointDescriptor;
import com.visioglobe.libVisioDevKit.VgPointDescriptorRefPtr;
import com.visioglobe.libVisioDevKit.VgPointDescriptorVector;
import com.visioglobe.libVisioDevKit.VgPosition;
import com.visioglobe.libVisioDevKit.VgSRSConstRefPtr;
import com.visioglobe.libVisioDevKit.VgSinusoidalVectorOffsetFunctorDescriptor;
import com.visioglobe.libVisioDevKit.VgSinusoidalVectorOffsetFunctorDescriptorRefPtr;
import com.visioglobe.libVisioDevKit.libVisioDevKit;

public class VgMyRoutingHelper implements 
    VgMyRouteCreator,
    VgMyRouteDisplay,
    VgMyPoiConfigurationSetter
{
    public class FloorChangeCallback extends VgIGeometryCallback {

        private String mLayerName;
        private VgMyLayerAndCameraHandler mLayerAndCameraHandler = null;

        public FloorChangeCallback(VgMyLayerAndCameraHandler pLayerAndCameraHandler, String pLayerName) 
        {
            super();
            mLayerName = pLayerName;
            mLayerAndCameraHandler = pLayerAndCameraHandler;
        }

        @Override
        public void handleGeometryEvent(VgIGeometryEvent pEvent) 
        {
            mLayerAndCameraHandler.gotoLayer(mLayerName, true);
        }
    };
    
    VgMyTextureLoader mTextureLoader = null;
    VgMySurfaceView mSurfaceView = null;
    VgIRoutingModule mRoutingModule = null;
    VgIMapModule mMapModule = null;
    VgMyGeometryManager mGeometryManager = null;
    VgMyRouteStyler mRouteStyler = null;
    private VgIRouteCallbackRefPtr mRouteCallback = null;
    private VgMyLayerAndCameraHandler mLayerAndCameraHandler = null;
    
    // Object types
    public static final String cRoutingObjects = "routingObjects";
    public static final String cMarkerObjects = "markerObjects";

    // Storing the routing nodes
    protected HashMap<RoutePoint, VgIRoutingNodeRefPtr> mRoutePoints = null;
    
    // Request parameters to enable route requests for buses, wheelchair 
    // only, etc   
    VgIRouteRequestParameters mRoutingRequestParameters;
    
    VgSinusoidalVectorOffsetFunctorDescriptorRefPtr mSinusoidalFuncDescr = null;
    VgAxialRotationQuaternionFunctorDescriptorRefPtr mAxialFuncDesc = null;
    
    private final float cGeometryConstantSizeDistance = 100.0f;
    private final float cVisibilityRampStartVisible = 1.0f;
    private final float cVisibilityRampFullyVisible = 5.0f;
    private final float cVisibilityRampStartInvisible = 900.0f;
    private final float cVisibilityRampFullyInvisible = 1000.0f;
    
    private boolean mIsVisible = false;

    
    public VgMyRoutingHelper(VgMySurfaceView pSurfaceView, VgMyTextureLoader pTextureLoader, VgMyGeometryManager pGeometryManager, VgIRouteCallbackRefPtr pRouteCallback, VgMyLayerAndCameraHandler pLayerAndCameraHandler)
    {
        mSurfaceView = pSurfaceView;
        mTextureLoader = pTextureLoader;
        mGeometryManager = pGeometryManager;
        mRouteCallback = pRouteCallback;
        mLayerAndCameraHandler = pLayerAndCameraHandler;
        mRouteStyler = new VgMyRouteStyler(mSurfaceView.getApplication());
        mRoutePoints = new HashMap<RoutePoint, VgIRoutingNodeRefPtr>();
        
        resetRoutingRequestParameters();
        
        if (mSurfaceView == null) {
            return;
        }
        
        VgIApplication lApplication = mSurfaceView.getApplication();
        if (lApplication == null) {
            return;
        }
        VgIModuleManager lModuleManager = lApplication.editModuleManager();
        if (lModuleManager == null) {
            return;
        }
        VgIModule lRoutingModule = lModuleManager.queryModule("Routing");
        if (lRoutingModule == null) {
            return;
        }
        mRoutingModule = libVisioDevKit.castToIRoutingModule(lRoutingModule);
        if (mRoutingModule == null) {
            return;
        }
        
        VgIModule lModule = lModuleManager.queryModule("Map");
        if (lModule == null) {
            return;
        }
        mMapModule = libVisioDevKit.castToIMapModule(lModule);
        if (mMapModule == null) 
        {
            return;
        }
        
        loadTextures();
    }
    
    private void loadTextures() {
        // Set Images
        mTextureLoader.setImage("start", R.drawable.track_start);
        mTextureLoader.setImage("end", R.drawable.track_end);
        mTextureLoader.setImage("stairsDown", R.drawable.track_stair_down);
        mTextureLoader.setImage("stairsUp", R.drawable.track_stair_up);   
        mTextureLoader.setImage("track", R.drawable.track);
        mTextureLoader.setImage("trackBase", R.drawable.track_base);
        
        // Set Markers
        mTextureLoader.setMarker("start", "start");
        mTextureLoader.setMarker("end", "end");
        mTextureLoader.setMarker("stairsDown", "stairsDown");
        mTextureLoader.setMarker("stairsUp", "stairsUp");
    }
    
    
    protected boolean isPlaceRoutable(String pPlaceId) 
    {
        if (mRoutingModule == null) {
            return false;
        }
        VgIRoutingNodeRefPtr lNode = mRoutingModule.getRoutingSolver().getRoutingNode(pPlaceId);
        return lNode.isValid();
    }
            
    protected VgPosition getPositionOfPlace(String pPlaceId)        
    {       
        VgPosition lPos = null;     

        if(null == mMapModule)
        {
            return null;
        }

        if(pPlaceId != null)        
        {
            VgPlaceDescriptor lPlaceDesc = new VgPlaceDescriptor();
            mMapModule.queryPlaceDescriptor(pPlaceId, lPlaceDesc);

            lPos = lPlaceDesc.getMViewpoint().getMPosition();
            
            float[] lHeightMax = new float[1];
            float[] lHeightMin = new float[1];
            double lFloorHeight = 0.0;
            
            if (mMapModule.getHeightRangeForLayer(lPlaceDesc.getMLayerName(), lHeightMax, lHeightMin))
            {
                lFloorHeight = ((lHeightMax[0] + lHeightMin[0]) / 2);
            }
            lPos.setMZOrAltitude(lFloorHeight);
        }       

        return lPos;        
    }
    
    protected String getLayerNameForPosition(VgPosition pPosition)
    {
        String lLayerName = "";
        
        if(null == mMapModule)
        {
            return null;
        }
        
        String[] lOutputLayerName = new String[1];
        if(true == mMapModule.getLayerForPosition(pPosition, lOutputLayerName))
        {
            lLayerName = lOutputLayerName[0];
        }
        
        return lLayerName; 
    }
    
    protected void createAndAddRouteMarker(RoutePoint pRoutePoint, VgPosition pPosition)
    {
        // Get layer name using position altitude
        String lLayerName = getLayerNameForPosition(pPosition);
        // Set the altitude which will be the distance of the marker above the floor
        pPosition.setMZOrAltitude(7.0f);
        
        mGeometryManager.removeObjects(cMarkerObjects);
        mGeometryManager.deleteObjects(cMarkerObjects);
        
        VgPointDescriptorRefPtr lPointDescr = VgPointDescriptor.create();
        lPointDescr.setMVisibilityRampStartVisible(cVisibilityRampStartVisible);
        lPointDescr.setMVisibilityRampFullyVisible(cVisibilityRampFullyVisible);
        lPointDescr.setMVisibilityRampStartInvisible(cVisibilityRampStartInvisible);
        lPointDescr.setMVisibilityRampFullyInvisible(cVisibilityRampFullyInvisible);
        lPointDescr.setMGeometryConstantSizeDistance(cGeometryConstantSizeDistance);
        lPointDescr.setMAnchorPosition(VgAnchorMode.eVgBottomCenter);
        lPointDescr.setMPosition(pPosition);
        lPointDescr.setMDrawOnTop(true);
        
        
        VgMarkerDescriptorRefPtr lTrackStartMarkerDesc = VgMarkerDescriptorRefPtr.getNull();
        
        if(pRoutePoint == RoutePoint.eStart)
        {
            lTrackStartMarkerDesc = mTextureLoader.getMarker("start");
        }
        else
        {
            lTrackStartMarkerDesc = mTextureLoader.getMarker("end");
        }
        
        if (lTrackStartMarkerDesc != null) 
        {
            VgMarkerDescriptorVector lMarkerDescVec = new VgMarkerDescriptorVector();
            lMarkerDescVec.add(lTrackStartMarkerDesc);
            lPointDescr.setMMarkerDescriptors(lMarkerDescVec);
            lPointDescr.setMAnchorPosition(VgAnchorMode.eVgBottomCenter);
        }


        PointObject lPointObject = mGeometryManager.createPointObject(cMarkerObjects, lLayerName, lPointDescr, VgIGeometryCallbackRefPtr.getNull());
        mGeometryManager.addObjects(cMarkerObjects);
        
        if (null != lPointObject.mPoint)
        {
            VgAnimationRefPtr lAnimation = getRoutePointHighlightAnimationDescriptor();
            lPointObject.mPoint.setAnimation("",lAnimation);
            lAnimation.start();
        }
    }

    // Creates a position animation
    protected VgAnimationRefPtr getRoutePointHighlightAnimationDescriptor() 
    {
        // Set up a small animation to emphasize the point.
        VgAnimationDescriptorRefPtr lAnimDescr = VgAnimationDescriptor.create();
        lAnimDescr.setMDuration((float) 2.0);
        lAnimDescr.setMCallback(VgIAnimationCallbackRefPtr.getNull());
        lAnimDescr.setMLoopMode(VgLoopModes.getMscLoop());
        
        boolean lAnimatePosition = true;
        if (lAnimatePosition)
        {
            VgFunctorDescriptorRefPtr lPosFuncDesc = getSinusoidalFuncDesc();
            lAnimDescr.getMFunctorDescriptors().set(VgAnimationChannels.getMscLocalPositionChannel(), lPosFuncDesc);
        }
        
        boolean lAnimateRotation = false;
        if (lAnimateRotation)
        {
            VgFunctorDescriptorRefPtr lOrientFuncDesc = getAxialFuncDesc();
            lAnimDescr.getMFunctorDescriptors().set(VgAnimationChannels.getMscLocalOrientationChannel(), lOrientFuncDesc);
        }

        VgAnimationRefPtr lAnimation = mSurfaceView.getApplication().editEngine().editInstanceFactory().instantiate(lAnimDescr);
        return lAnimation;
    }
    

    // Creates a sinusoidal description
    VgFunctorDescriptorRefPtr getSinusoidalFuncDesc ()
    {
        if (null == mSinusoidalFuncDescr)
        {
            VgSinusoidalVectorOffsetFunctorDescriptorRefPtr lSinusoidalFuncDesc = VgSinusoidalVectorOffsetFunctorDescriptor.create();
            lSinusoidalFuncDesc.setMStartPhase(- Math.PI);
            lSinusoidalFuncDesc.setMEndPhase(Math.PI);
            
            float[] lBaseVector = new float[3];
            lBaseVector[0] = 0.0f;
            lBaseVector[1] = 5.0f;
            lBaseVector[2] = 0.0f;
            lSinusoidalFuncDesc.setMBaseVector(lBaseVector);
            
            float[] lVector = new float[3];
            lVector[0] = 0.0f;
            lVector[1] = 2.5f;
            lVector[2] = 0.0f;
            lSinusoidalFuncDesc.setMVector(lVector);
        
            mSinusoidalFuncDescr = lSinusoidalFuncDesc;
        }
        return new VgFunctorDescriptorRefPtr(mSinusoidalFuncDescr.get());
    }

    
    // Creates an axial rotation description.
    VgFunctorDescriptorRefPtr getAxialFuncDesc ()
    {
        if (null == mAxialFuncDesc)
        {
            VgAxialRotationQuaternionFunctorDescriptorRefPtr lOrientFuncDesc = VgAxialRotationQuaternionFunctorDescriptor.create();
            float[] lVector = new float[3];
            lVector[0] = 0.0f;
            lVector[1] = 0.0f;
            lVector[2] = 1.0f;
            
            lOrientFuncDesc.setMAxis(lVector);

            lOrientFuncDesc.setMStartAngle(-45.0f);
            lOrientFuncDesc.setMEndAngle(45.0f);
            lOrientFuncDesc.setMCubic(true);
            
            mAxialFuncDesc = lOrientFuncDesc;
        }
        return new VgFunctorDescriptorRefPtr(mAxialFuncDesc.get());
    }
    
    protected VgIRouteGeometryDescriptorVector get2DRouteDescriptors(VgIRouteConstRefPtr pRoute) 
    {
        if (mRoutingModule == null) {
            return null;
        }
        VgIRouteConverter lConverter = mRoutingModule.getRouteConverterFactory().createConverter(
                VgIRouteConverterType.e2D);
        VgIRouteGeometryDescriptorVector lRouteDescriptors = new VgIRouteGeometryDescriptorVector();
        lConverter.convertRoute(pRoute, lRouteDescriptors);
        return lRouteDescriptors;
    }
    
    protected double computeFloorHeightFromLayer (String pLayerName)
    {
        double lFloorHeight = 0.0;
 
        if (null == mMapModule) {
            return lFloorHeight;
        }

        float[] lHeightMax = new float[1];
        float[] lHeightMin = new float[1];
        if ( mMapModule.getHeightRangeForLayer(pLayerName, lHeightMax, lHeightMin))
        {
            lFloorHeight = ((lHeightMax[0] + lHeightMin[0]) / 2);
        }
       
        return lFloorHeight;
    }
    
    /********************************************************
     * @implements VgMyRouteCreator
     * 
     */
    
    // returns false, if no routing node.
    public boolean setRoutePoint(final RoutePoint pPoint, final String pPlaceID)
    {
        boolean lSuccess = false;

        if ( (null != pPlaceID) && 
                isPlaceRoutable(pPlaceID) )
        {
            VgIRoutingNodeRefPtr lNode = mRoutingModule.getRoutingSolver().getRoutingNode(pPlaceID);

            if(lNode.isValid())
            {
                mRoutePoints.put(pPoint, lNode);
                
                VgPosition lPos = getPositionOfPlace(pPlaceID);
                createAndAddRouteMarker(pPoint, lPos);

                lSuccess = true;
            }
        }
        
        return lSuccess;
    }

    // returns false, if no routing node found for position.
    public boolean setRoutePoint(final RoutePoint pPoint, final VgPosition pPosition)
    {
        boolean lSuccess = false;

        VgIRoutingNodeRefPtr lNode = mRoutingModule.getRoutingSolver().getRoutingNode(pPosition);

        if(lNode.isValid())
        {
            mRoutePoints.put(pPoint, lNode);

            createAndAddRouteMarker(pPoint, pPosition);
            lSuccess = true;
        }
        
        return lSuccess;
    }
    
    public void resetRoutePoint(final RoutePoint pPoint)
    {       
        mRoutePoints.remove(pPoint);

        // Remove any markers associated with the route points
        mGeometryManager.removeObjects(cMarkerObjects);
        mGeometryManager.deleteObjects(cMarkerObjects);
    }

    public boolean isRoutePointSet(RoutePoint pPoint)
    {
        boolean lIsSet = mRoutePoints.containsKey(pPoint);
        return lIsSet;
    }

    public void computeRoute()
    {
        if(isRoutePointSet(RoutePoint.eStart) &&
                isRoutePointSet(RoutePoint.eEnd) && 
                (mRouteCallback != null) &&
                (mRouteCallback.isValid()))
        {
            VgIRouteRequestParameters lRouteRequestParams = mRoutingRequestParameters;
            VgIRoutingNodeRefPtr lRoutingNodeStart = mRoutePoints.get(RoutePoint.eStart);
            lRouteRequestParams.setMOrigin(lRoutingNodeStart);
            VgIRoutingNodeRefPtrVector lNodeVector = new VgIRoutingNodeRefPtrVector();
            VgIRoutingNodeRefPtr lRoutingNodeEnd = mRoutePoints.get(RoutePoint.eEnd);
            lNodeVector.add(lRoutingNodeEnd);
            lRouteRequestParams.setMDestinations(lNodeVector);
            lRouteRequestParams.setMCallback(mRouteCallback);
            VgIRoutingSolver lSolver = mRoutingModule.getRoutingSolver();
            lSolver.computeRoute(lRouteRequestParams);

            // Reset the route points after use.
            resetRoutePoint(RoutePoint.eEnd);
            resetRoutePoint(RoutePoint.eStart);
        }
    }
    
    public VgIRouteRequestParameters editRoutingRequestParameters() 
    {
        return mRoutingRequestParameters;
    }

    public void resetRoutingRequestParameters() 
    {
        VgIRouteRequestParameters lBase = new VgIRouteRequestParameters();
        // INSERT HERE any customization to the defaults.
        mRoutingRequestParameters = lBase;
    }
    
    public void setAvoidStairs (boolean pDisabledFriendly)
    {
        final String[] lscAttributes = {
                "stairs",
                "stairway",
                "escalator"
        };

        for(int i = 0; i < lscAttributes.length; i++)
        {
            if(true == pDisabledFriendly)
            {
                mRoutingRequestParameters.getMExcludedAttributes().insert(lscAttributes[i]);
            }
            else
            {
                mRoutingRequestParameters.getMExcludedAttributes().del(lscAttributes[i]);
            }
        }   
    }

    /********************************************************
     * @implements VgMyRouteDisplay
     * 
     */


    public boolean createRouteObjects(final VgIRouteConstRefPtr pRoute)
    {
        if ((pRoute != null) &&
            (pRoute.isValid()) ) 
        {
            if (mGeometryManager != null) {
                // Remove previous routing objects
                mGeometryManager.removeObjects(cRoutingObjects);
                mGeometryManager.deleteObjects(cRoutingObjects);
                // Convert route to geometry descriptors
                VgIRouteGeometryDescriptorVector lRouteDescriptors = get2DRouteDescriptors(pRoute);

                VgPosition lLastPos = new VgPosition ();
                boolean lFirstLine = true;

                // Iterate through geometry descriptors
                for (int lRouteGeomIdx = 0; lRouteGeomIdx < lRouteDescriptors.size(); ++lRouteGeomIdx) 
                {
                    VgIRouteGeometryDescriptor lRouteDescr = lRouteDescriptors.get(lRouteGeomIdx);
                    VgLineDescriptorVector lLineDescriptors = lRouteDescr.getMLineDescriptors();
                    // Create line strings
                    for (int lLineNum = 0; lLineNum < lLineDescriptors.size(); ++lLineNum) 
                    {
                        VgLineDescriptorRefPtr lLineDescr = lLineDescriptors.get(lLineNum);

                        VgMyRouteStyler.RouteStyleParameters lStyleParams = mRouteStyler.new RouteStyleParameters();
                        lStyleParams.mAgentColor = new VgColor(1.0f,1.0f,1.0f,1.0f);
                        lStyleParams.mTrackColor = new VgColor(1.0f,1.0f,1.0f,1.0f);
                        lStyleParams.mTrackBase = mTextureLoader.getTextureBuffer("trackBase");
                        lStyleParams.mTrackAgent = mTextureLoader.getTextureBuffer("track");
                        mRouteStyler.styleRoute(VgMyRouteStyler.RouteStyle.eSimplifiedMultiLinePlusAgent, lStyleParams, lLineDescr, mGeometryManager, lRouteDescr.getMLayerName());
                        
                        
                        if (!lFirstLine)
                        {
                            VgITextureRefPtr lLinkTexture = mTextureLoader.getTextureBuffer("track");
                            VgLinkDescriptorRefPtr lLinkDesc = VgLinkDescriptor.create();
                            if ((lLinkTexture != null) && (lLinkTexture.isValid()))
                            {
                                lLinkDesc.setMTexture(lLinkTexture);
                            }
                            lLinkDesc.setMSourcePosition(lLastPos);
                            lLinkDesc.getMSourcePosition().setMZOrAltitude(0.0f);
                            VgPosition lTargetPos = new VgPosition ( lLineDescr.getMPositions().get(0) );
                            lTargetPos.setMSRS(mSurfaceView.getApplication().editEngine().editLayerManager().editLayer(lRouteDescr.getMLayerName()).getSRS());
                            lLinkDesc.setMTargetPosition(lTargetPos);
                            lLinkDesc.getMTargetPosition().setMZOrAltitude(0.0f);

                            lLinkDesc.setMWidth(10.0f);
                            lLinkDesc.setMTextureRatio(1.0f);
                            lLinkDesc.setMAnimationSpeed(10.0f);

                            mGeometryManager.createLinkObject(cRoutingObjects, lLinkDesc);
                        }

                        lFirstLine = false;
                        lLastPos = lLineDescr.getMPositions().get((int)lLineDescr.getMPositions().size()-1);
                        VgSRSConstRefPtr lSRS = mSurfaceView.getApplication().editEngine().editLayerManager().editLayer(lRouteDescr.getMLayerName()).getSRS();
                        lLastPos.setMSRS(lSRS);
                    }

                    VgMarkerDescriptorRefPtr lTrackStairsUpMarkerDesc = mTextureLoader.getMarker("stairsUp");
                    VgMarkerDescriptorRefPtr lTrackStairsDownMarkerDesc = mTextureLoader.getMarker("stairsDown");

                    // Create POIs
                    VgPointDescriptorVector lPoiDescriptors = lRouteDescr.getMPointDescriptors();
                    for (int lPoiIdx = 0; lPoiIdx < lPoiDescriptors.size(); ++lPoiIdx) 
                    {
                        // The various POI's can be configured differently.  POI's can have
                        // callbacks (this is optional) to allow specific responses to notification 
                        // events.
                        // Furthermore, icon images can be configured to provide informative visual feedback.
                        VgPointDescriptorRefPtr lPointDescr = lPoiDescriptors.get(lPoiIdx);
                        lPointDescr.setMVisibilityRampStartVisible(cVisibilityRampStartVisible);
                        lPointDescr.setMVisibilityRampFullyVisible(cVisibilityRampFullyVisible);
                        lPointDescr.setMVisibilityRampStartInvisible(cVisibilityRampStartInvisible);
                        lPointDescr.setMVisibilityRampFullyInvisible(cVisibilityRampFullyInvisible);
                        lPointDescr.setMGeometryConstantSizeDistance(cGeometryConstantSizeDistance);
                        lPointDescr.setMAnchorPosition(VgAnchorMode.eVgBottomCenter);
                        lPointDescr.setMDrawOnTop(true);
                        
                        VgAnimationRefPtr lAnimation = null;

                        VgIGeometryCallbackRefPtr lPoiCallback = VgIGeometryCallbackRefPtr.getNull();
                        if (lPoiIdx == 0) 
                        {
                            if (lRouteGeomIdx == 0) 
                            {
                                VgMarkerDescriptorRefPtr lTrackStartMarkerDesc = mTextureLoader.getMarker("start");
                                if ((lTrackStartMarkerDesc != null) &&
                                        (lTrackStartMarkerDesc.isValid())) 
                                {
                                    VgMarkerDescriptorVector lMarkerDescVec = new VgMarkerDescriptorVector();
                                    lMarkerDescVec.add(lTrackStartMarkerDesc);
                                    lPointDescr.setMMarkerDescriptors(lMarkerDescVec);
                                    lPointDescr.setMAnchorPosition(VgAnchorMode.eVgCenterRight);
                                    
                                    lAnimation = getRoutePointHighlightAnimationDescriptor();
                                }
                            }
                            else 
                            {
                                final String lPreviousDatasetName = lRouteDescriptors.get(lRouteGeomIdx - 1).getMLayerName();
                                lPoiCallback = new VgIGeometryCallbackRefPtr(new FloorChangeCallback(mLayerAndCameraHandler, lPreviousDatasetName));
                                
                                if(computeFloorHeightFromLayer(lPreviousDatasetName) == computeFloorHeightFromLayer(lRouteDescr.getMLayerName()))
                                {
                                    // Change of modality, do not show a change floor icon.
                                    continue;
                                }
                                else if (computeFloorHeightFromLayer(lPreviousDatasetName) > computeFloorHeightFromLayer(lRouteDescr.getMLayerName())) 
                                {
                                    if ((lTrackStairsUpMarkerDesc != null) &&
                                            (lTrackStairsUpMarkerDesc.isValid())) 
                                    {

                                        VgMarkerDescriptorVector lMarkerDescVec = new VgMarkerDescriptorVector();
                                        lMarkerDescVec.add(lTrackStairsUpMarkerDesc);
                                        lPointDescr.setMMarkerDescriptors(lMarkerDescVec);
                                        // we offset the stair icons, just in case there are two stairs icon on the same spot.
                                        lPointDescr.setMAnchorPosition(VgAnchorMode.eVgBottomRight);
                                    }
                                } 
                                else 
                                {
                                    if (lTrackStairsDownMarkerDesc != null) 
                                    {
                                        VgMarkerDescriptorVector lMarkerDescVec = new VgMarkerDescriptorVector();
                                        lMarkerDescVec.add(lTrackStairsDownMarkerDesc);
                                        lPointDescr.setMMarkerDescriptors(lMarkerDescVec);
                                        lPointDescr.setMAnchorPosition(VgAnchorMode.eVgTopRight);
                                    }
                                }
                            }
                        } 
                        else if (lPoiIdx == lPoiDescriptors.size() - 1) 
                        {
                            if (lRouteGeomIdx == lRouteDescriptors.size() - 1) 
                            {
                                VgMarkerDescriptorRefPtr lTrackEndMarkerDesc = mTextureLoader.getMarker("end");
                                if ((lTrackEndMarkerDesc != null) &&
                                        (lTrackEndMarkerDesc.isValid())) 
                                {
                                    VgMarkerDescriptorVector lMarkerDescVec = new VgMarkerDescriptorVector();
                                    lMarkerDescVec.add(lTrackEndMarkerDesc);
                                    lPointDescr.setMMarkerDescriptors(lMarkerDescVec);
                                    lPointDescr.setMAnchorPosition(VgAnchorMode.eVgCenterLeft);
                                    
                                    lAnimation = getRoutePointHighlightAnimationDescriptor();
                                }
                            } 
                            else 
                            {
                                final String lNextDatasetName = lRouteDescriptors.get(lRouteGeomIdx + 1).getMLayerName();
                                lPoiCallback = new VgIGeometryCallbackRefPtr(new FloorChangeCallback(mLayerAndCameraHandler, lNextDatasetName));
                                
                                if(computeFloorHeightFromLayer(lNextDatasetName) == computeFloorHeightFromLayer(lRouteDescr.getMLayerName()))
                                {
                                    // Change of modality, do not show a change floor icon.
                                    continue;
                                }
                                else if (computeFloorHeightFromLayer(lNextDatasetName) > computeFloorHeightFromLayer(lRouteDescr.getMLayerName())) 
                                {

                                    if ((lTrackStairsUpMarkerDesc != null) &&
                                            (lTrackStairsUpMarkerDesc.isValid()))  
                                    {
                                        VgMarkerDescriptorVector lMarkerDescVec = new VgMarkerDescriptorVector();
                                        lMarkerDescVec.add(lTrackStairsUpMarkerDesc);
                                        lPointDescr.setMMarkerDescriptors(lMarkerDescVec);
                                        lPointDescr.setMAnchorPosition(VgAnchorMode.eVgBottomLeft);
                                    }
                                } 
                                else 
                                {
                                    if ((lTrackStairsDownMarkerDesc != null) &&
                                            (lTrackStairsDownMarkerDesc.isValid()))
                                    {
                                        VgMarkerDescriptorVector lMarkerDescVec = new VgMarkerDescriptorVector();
                                        lMarkerDescVec.add(lTrackStairsDownMarkerDesc);
                                        lPointDescr.setMMarkerDescriptors(lMarkerDescVec);
                                        lPointDescr.setMAnchorPosition(VgAnchorMode.eVgTopLeft);
                                    }
                                }
                            }
                        }
                        lPointDescr.getMPosition().setMZOrAltitude(10.0f);
                        
                        PointObject lPointObject = mGeometryManager.createPointObject(cRoutingObjects, lRouteDescr.getMLayerName(), lPointDescr, lPoiCallback);

                        if ((null != lPointObject.mPoint) &&
                                (null != lAnimation) &&
                                (lAnimation.isValid()))
                        {
                            lPointObject.mPoint.setAnimation("", lAnimation);
                            lAnimation.start(); 
                        }
                    }
                }               
            }
        }

        return true;
    }

    public void clear()
    {
        hide();

        if ( mGeometryManager != null) 
        {
            mGeometryManager.deleteObjects(cRoutingObjects);
            mGeometryManager.deleteObjects(cMarkerObjects);
        }
    }


    public void show()
    {
        if ( mGeometryManager != null) 
        {
            // Use routing context to identify routing objects maintained by component 3d
            mGeometryManager.addObjects(cRoutingObjects);
            mGeometryManager.addObjects(cMarkerObjects);
            mIsVisible = true;
        }       
    }

    public void hide()
    {
        if ( mGeometryManager != null) 
        {
            // Use routing context to identify routing objects maintained by component 3d
            mGeometryManager.removeObjects(cRoutingObjects);
            mGeometryManager.removeObjects(cMarkerObjects);
            mIsVisible = false;
        }   
    }
    
    public boolean isVisible()
    {
        return mIsVisible;
    }

    /********************************************************
     * @implements VgMyPoiConfigurationSetter
     * 
     */
    public void setPoiCallback(String pIdentifier, VgIGeometryCallback pCallback)
    {
        Log.i("Vg", "setPoiCallback() - > implement this method if desired");
    }

    @Override
    public void release()
    {
        mGeometryManager.removeObjects(cRoutingObjects);
        mGeometryManager.deleteObjects(cRoutingObjects);
        mGeometryManager.removeObjects(cMarkerObjects);
        mGeometryManager.deleteObjects(cMarkerObjects);
        if (mRoutingRequestParameters != null)
        {
            mRoutingRequestParameters.setMCallback(VgIRouteCallbackRefPtr.getNull());
            mRoutingRequestParameters = null;
        }
        
        mRouteCallback = null;
    }
}

./Common/Makefiles/Android/src/com/visioglobe/VisioSample/Blocks/VgMyStackedLayerAndCameraHandler.java

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

package com.visioglobe.VisioSample.Blocks;

import java.util.HashMap;

import com.visioglobe.VisioSample.VgMySurfaceView;
import com.visioglobe.VisioSample.Interfaces.VgMyLayerAndCameraHandler;
import com.visioglobe.VisioSample.Interfaces.VgMyLayerAndCameraListener;
import com.visioglobe.libVisioDevKit.VgAnimationChannels;
import com.visioglobe.libVisioDevKit.VgAnimationDescriptor;
import com.visioglobe.libVisioDevKit.VgAnimationDescriptorRefPtr;
import com.visioglobe.libVisioDevKit.VgAnimationRefPtr;
import com.visioglobe.libVisioDevKit.VgAxialRotationQuaternionFunctorDescriptor;
import com.visioglobe.libVisioDevKit.VgAxialRotationQuaternionFunctorDescriptorRefPtr;
import com.visioglobe.libVisioDevKit.VgFunctorDescriptorRefPtr;
import com.visioglobe.libVisioDevKit.VgGestureState;
import com.visioglobe.libVisioDevKit.VgIAnimationCallback;
import com.visioglobe.libVisioDevKit.VgIAnimationCallbackRefPtr;
import com.visioglobe.libVisioDevKit.VgIApplication;
import com.visioglobe.libVisioDevKit.VgICamera;
import com.visioglobe.libVisioDevKit.VgIDatabaseDatasetDescriptor;
import com.visioglobe.libVisioDevKit.VgIManipulatorManager;
import com.visioglobe.libVisioDevKit.VgISimpleGestureManipulatorListener;
import com.visioglobe.libVisioDevKit.VgISimpleGestureManipulatorListenerRefPtr;
import com.visioglobe.libVisioDevKit.VgIViewPoint;
import com.visioglobe.libVisioDevKit.VgLayerRefPtr;
import com.visioglobe.libVisioDevKit.VgLayerVector;
import com.visioglobe.libVisioDevKit.VgManipulator;
import com.visioglobe.libVisioDevKit.VgPosition;
import com.visioglobe.libVisioDevKit.VgPositionToolbox;
import com.visioglobe.libVisioDevKit.VgPositionVector;
import com.visioglobe.libVisioDevKit.VgQuaternionInterpolationFunctorDescriptor;
import com.visioglobe.libVisioDevKit.VgQuaternionInterpolationFunctorDescriptorRefPtr;
import com.visioglobe.libVisioDevKit.VgSRSConstRefPtr;
import com.visioglobe.libVisioDevKit.VgSimpleGestureManipulator;
import com.visioglobe.libVisioDevKit.VgSpatialRefPtr;
import com.visioglobe.libVisioDevKit.VgVectorInterpolationFunctorDescriptor;
import com.visioglobe.libVisioDevKit.VgVectorInterpolationFunctorDescriptorRefPtr;
import com.visioglobe.libVisioDevKit.libVisioDevKit;

public class VgMyStackedLayerAndCameraHandler 
    implements 
        VgMyLayerAndCameraHandler
{
    
    
    class StopAnimationCallback extends VgIAnimationCallback
    {
    
        StopAnimationCallback(VgSpatialRefPtr pSpatial, VgIManipulatorManager pManipMgr, VgMyStackedLayerAndCameraHandler pSelector) 
        {
            super();
            mManipMgr = pManipMgr;
            mSpatial = pSpatial;
            mSelector = pSelector;
        }
        
        @Override
        public void onFinish (VgAnimationRefPtr pAnimation)
        {
            if ((mSpatial != null) && mSpatial.isValid())
            {
                mSpatial.setAnimation("",VgAnimationRefPtr.getNull());
            }
            
            if (mManipMgr != null && mSelector != null)
            {
                mSelector.updateManipulatorForGlobalView( mSelector.isGlobalView() );
            }
        }

        protected VgSpatialRefPtr mSpatial;
        protected VgIManipulatorManager mManipMgr;
        protected VgMyStackedLayerAndCameraHandler mSelector;
    };
    
    
    class LayerHideCallback extends VgIAnimationCallback
    {    
        LayerHideCallback(VgLayerRefPtr lLayer)
        {
            super();
            mLayer = lLayer;
        }
        
        @Override
        public void onFinish(VgAnimationRefPtr pAnimation)
        {
            if (mLayer!=null && mLayer.isValid())
            {
                mLayer.setVisible(false);
                mLayer.setHostedVisible(false);
            }
        }
        
        protected VgLayerRefPtr mLayer;
    };
    
    class FloorSelectorManipulator extends VgISimpleGestureManipulatorListener
    {
    
        FloorSelectorManipulator(VgIApplication pApplication, VgMyStackedLayerAndCameraHandler pSelector, long pWidth, long pHeight)
        {
            super();
            mSelector = pSelector;
            mApplication = pApplication;
            mDragTotalOffsetY = 0;
            mDragGestureStarted = false;
            mPinchGestureStarted = false;
            mOriginalSpan = 0;
            mWidth = pWidth;
            mHeight = pHeight;
        }
        
        public void onDoubleClick (float x, float y)
        {
        }


        // Implements, single click on middle third screen to switch to detailed view.
        public void onClick (float x, float y)
        {
            if (y < 0.33f)
            {
                mSelector.gotoLayer(mSelector.getCurrentLayerIndex()+1, true);
                
            }
            else if (y > 0.66f)
            {
                mSelector.gotoLayer(mSelector.getCurrentLayerIndex()-1, true);
            }
            else
            {
                // and middle third of screen.
                mSelector.switchToDetailedView(true);            
            }
        }       
        
        @Override
        public void onSimplePinch(VgGestureState pState, float pSpan, float pVelocity)
        {
            if (mDragGestureStarted)
            {
                cancelDragGesture();
                return;
            }
            
            if (pState == VgGestureState.eVgGestureEnd)
            {
                cancelPinchGesture();
                return;
            }
            
            if (pState == VgGestureState.eVgGestureBegin)
            {
                mPinchGestureStarted = true;
                mOriginalSpan = pSpan;
            }
            
            if (!mPinchGestureStarted)
            {
                return ;
            }
            
            float lMaxSpanValue = Math.max(mWidth, mHeight);
            
            float lSpanDiff = mOriginalSpan - pSpan;
                        
            // Zoom-in/out a little
            VgPositionToolbox lToolbox = mApplication.editEngine().getPositionToolbox();
            VgICamera lCamera = mApplication.editEngine().editCamera();
            VgLayerVector lLayers = mApplication.editEngine().editLayerManager().editLayers();
            if(lLayers.size() > mSelector.mCurrentLayerIndex)
            {
                VgPosition lOriginalPos = lToolbox.offsetPosition(mSelector.getStackCenter(), 
                        mApplication.editEngine().editCamera().getHeading(), 
                        mApplication.editEngine().editCamera().getPitch(), 
                        - mSelector.getParam(VgMyConfigurableParam.eStackViewDistance));
                VgPosition lEndPos = lToolbox.offsetPosition(lOriginalPos, 
                        lCamera.getHeading(),
                        lCamera.getPitch(),
                        -mSelector.getParam(VgMyConfigurableParam.eStackViewDistance) * 0.75f * lSpanDiff / lMaxSpanValue);
                lCamera.setPosition(lEndPos);
            }
        }
        
        public void onSimpleDrag(VgGestureState pState, long pNbTouch, float pAverageXOffset, float pAverageYOffset)
        {
            if (pNbTouch != 1)  // In this case, it reacts only to single finger drags.
            {
                return;
            }
            
            if (mPinchGestureStarted)
            {
                cancelPinchGesture();
                return;
            }
            
            if (pState == VgGestureState.eVgGestureEnd)
            {
                cancelDragGesture();
                return;
            }
            
            if (pState == VgGestureState.eVgGestureBegin)
            {
                mDragGestureStarted = true;
            }
            
            if (!mDragGestureStarted)
            {
                return;
            }
            
            mDragTotalOffsetY += (int)pAverageYOffset;
            
            long lCurrentLayer = mSelector.mCurrentLayerIndex;
            
            boolean lIsManipulatingUpperLayer = (mDragTotalOffsetY < 0.f);
            long lFloorToMove = lIsManipulatingUpperLayer ? lCurrentLayer + 1 : lCurrentLayer - 1;
            boolean lIsExtremityLayer = false;
            VgLayerVector lLayerList = mApplication.editEngine().editLayerManager().editLayers();
            if ((lFloorToMove < 0) || (lFloorToMove >= lLayerList.size()))
            {
                lIsExtremityLayer = true;
            }
            
            double lDragDistanceThreshold = mHeight * mSelector.getParam(VgMyConfigurableParam.eChangeLayerTriggerThreshold);
            
            // Change to the next floor if available once the user's drag enough 
            if (!lIsExtremityLayer && Math.abs(mDragTotalOffsetY) > lDragDistanceThreshold)
            {
                mSelector.gotoLayer(lFloorToMove, true); 
                mDragTotalOffsetY = 0;
                return;
            }
            
            // Move the layers while the user is dragging.
            double lcOffsetRatio = mHeight * 0.2f; // This Ratio determines how quickly the map moves given a drag offset. 
            // Calculate linear interpolation on Height...         
            double lOffset = mSelector.getParam(VgMyConfigurableParam.eLayerDistance) * pAverageYOffset / lcOffsetRatio;
            for (int iFloorIndex = (int)lLayerList.size() - 1; iFloorIndex >= 0; --iFloorIndex)
            {
                VgLayerRefPtr lLayerToMove = lLayerList.get(iFloorIndex);
                VgPosition lCurrentFloorPosition = new VgPosition(lLayerToMove.getPosition());
                lCurrentFloorPosition.setMZOrAltitude(lCurrentFloorPosition.getMZOrAltitude() + lOffset);
                lLayerToMove.setPosition(lCurrentFloorPosition);
            }
        }
        

        protected void cancelDragGesture() 
        {
            if (mDragGestureStarted && mDragTotalOffsetY != 0)
            {
                // If we drag through multiple layers, we need to animate back to the current position.
                // we cannot use gotoLayer, because it might make the stack "jump"
                mSelector.animateLayersFromCloseToStackView(eFromToViewEnum.eFromGlobalToGlobaView, (float) mSelector.getParam(VgMyConfigurableParam.eAnimateCancelDragDuration), true);
            }
            
            mDragTotalOffsetY = 0;
            mDragGestureStarted = false;
        }
        
        void cancelPinchGesture() {
            if (mPinchGestureStarted)
            {
                // Animate to the stacked multi layer view
                VgIViewPoint lViewPoint = mSelector.getStackViewPoint();
                mSelector.animateCameraToViewPoint(lViewPoint , (float) mSelector.getParam(VgMyConfigurableParam.eAnimateCancelPinchDuration), true);
            }
            
            mPinchGestureStarted = false;
        }
        
        public void setScreenSize(long pWidth, long pHeight)
        {
            mWidth = pWidth;
            mHeight = pHeight;
        }
        
        VgMyStackedLayerAndCameraHandler mSelector;
        VgIApplication mApplication;
        
        int mDragTotalOffsetY;
        boolean mDragGestureStarted;
        boolean mPinchGestureStarted;
        float mOriginalSpan;
        long mWidth;
        long mHeight;
    };
    
    
    

    /*
     * The below enum represents parameters that can be configured to
     * change the behaviour of the VgMyStackedLayerAndCameraHandler object.
     */
    public enum VgMyConfigurableParam
    {
        /*
         * This distance will be applied to the layers which are neighbouring 
         * the current layers when in detailed view.
         */
        eFarAwayHeight,
        /*
         * Heading used when the stack is displayed.  
         * Note: The default heading comes from "yaw" attribute of the "camera"
         * tag within the bundles configuration file.
         */
        eStackViewHeading,
        /*
         * Pitch used when the stack is displayed
         */
        eStackViewPitch,        
        /*
         * The maximum distance (meters) across the dataset.
         * Setting this parameter will automatically reset the following parameters:
         * - eStackViewDistance
         * - eLayerDistance
         * - eLayerDistanceFromCurrent
         * Note the default max size is calculated from the limits of the dataset 
         * indicated by the bundles configuration file.
         */
        eLayerMaxSize,
        /*
         * Distance between the camera and the layer stack.  
         *
         * Note: This param will be re-calculated automatically given the following conditions
         * - when eLayerMaxSize is set.
         * - when the refreshParameters(pWidth, pHeight) is called.
         *
         * When this value is calculated automatically, the camera will be displaced
         * just far enough away to ensure that the width of the eLayerMaxSize will fit
         * within the available view width.
         */
        eStackViewDistance,
        /*
         * Distance between layers (except ones around the current)
         *
         * Note: This param will be re-calculated automatically given the following conditions
         * - when eLayerMaxSize is set.
         * - when the refreshParameters(pWidth, pHeight) is called. 
         */
        eLayerDistance,
        /*
         * Distance between layers around the current
         *
         * Note: This param will be re-calculated automatically given the following conditions
         * - when eLayerMaxSize is set.
         * - when the refreshParameters(pWidth, pHeight) is called. 
         */
        eLayerDistanceFromCurrent, 
        /*
         * Duration of of camera animation when moving to detailed view.
         * Note : camera animation duration must be <= layer animation duration 
         * due to the manipulator change at the end of layers animation.
         */
        eAnimateToDetailCameraDuration,
        /*
         * Duration of camera animation when moving to global view  (seconds).
         */
        eAnimateToGlobalCameraDuration,
        /*
         * Duration of layer animation when moving to global view  (seconds).
         */
        eAnimateToGlobalLayerDuration,
        /*
         * See note assocated with eAnimateToDetailCameraDuration to see 
         * restrictions associated with this value  (seconds).
         */
        eAnimateToDetailLayerDuration,
        /*
         * Duration of animation when changing layer within the global view (seconds).
         */
        eAnimateChangeOfLayerDuration,
        /*
         * Duration of animation when cancelling a pinch gesture (seconds). 
         */
        eAnimateCancelPinchDuration,
        /*
         * Duration of animation when cancelling a drag gesture (seconds).
         */
        eAnimateCancelDragDuration,
        /*
         * Limits the maximum possible duration when animating to a view point
         */
        eAnimateMaxViewPointDuration, 
        /*
         * This threshold determines how long a draw is required in the global stack view before
         * the current layer is changed.
         * Measured as a percentage value [0.0 - 1.0] of the views pixel.
         */
        eChangeLayerTriggerThreshold,
        /*
         * Angle on stack view for non active layer (in degrees)
         */
        eStackNonActiveLayerAngle,
        /*
         * Angle on stack view for non active layer (in degrees)
         */
        eStackActiveLayerAngle,
        /*
         * DO NOT USE
         */
        eMaxDoubleParams
    }
    
    
    enum eFromToViewEnum
    {
        eFromStackToDetailedView,
        eFromDetailedToStackView,
        eFromGlobalToGlobaView // Used by cancel drag.
    };
    
    private VgIViewPoint mCamStartViewPoint;  // Viewpoint used in single layer view
    private VgPosition mStackCenter;  // Center of the stack
    
    // Contains all configurable parameters related to this object.
    // see the setParam and getParam methods for more details.
    double[] mParam = new double[VgMyConfigurableParam.eMaxDoubleParams.ordinal()];
    
    public long mCurrentLayerIndex; 
    private boolean mIsLayerStackDisplayed;
    private boolean mIsViewModeInitialized;
    private boolean mIsLayerInitialized;
    
    private VgIApplication mVgApplication;   // Pointer to the VisioDevKit
    private VgMySurfaceView mSurfaceView;
    
    private VgIAnimationCallbackRefPtr mCameraCallback;        // Camera Animation callback.
    private VgMyLayerAndCameraListener mLayerUpdateListener;
    private FloorSelectorManipulator mFloorSelectorManipulator;
    private VgISimpleGestureManipulatorListenerRefPtr mFloorSelectorManipulatorRefPtr;
    private HashMap<String, Float> mLODFactor = new HashMap<String, Float>();
    private HashMap<String, Float> mLoadFactor = new HashMap<String, Float>();
    private VgIViewPoint mCameraGlobalViewPoint = new VgIViewPoint();
    private VgSimpleGestureManipulator mSimpleGestureManipulator;
    
    public VgMyStackedLayerAndCameraHandler(VgMySurfaceView pSurfaceView, VgMyLayerAndCameraListener pLayerUpdateListener, long pViewWidthInPixels, long pViewHeightInPixels)
    {
        mSurfaceView = pSurfaceView;
        mVgApplication = mSurfaceView.getApplication();
        mLayerUpdateListener = pLayerUpdateListener;
        
        mCurrentLayerIndex = 0; 
        mIsLayerStackDisplayed = false;
        mIsViewModeInitialized = false;
        mIsLayerInitialized = false;
       
        // Register a VgISimpleGestureManipulatorListener to customize the gestures handling.
        VgManipulator lManipulator = mVgApplication.editManipulatorManager().editManipulatorObject("simpleGesture");
        mSimpleGestureManipulator = libVisioDevKit.castToVgSimpleGestureManipulator(lManipulator);

        mFloorSelectorManipulator = new FloorSelectorManipulator(mVgApplication, this, pViewHeightInPixels, pViewHeightInPixels);
        mFloorSelectorManipulatorRefPtr = new VgISimpleGestureManipulatorListenerRefPtr(mFloorSelectorManipulator);
        mSimpleGestureManipulator.setListener(mFloorSelectorManipulatorRefPtr);
        
        setDefaultStackParams();
        
        refreshParameters(pViewWidthInPixels, pViewHeightInPixels);

        mCameraCallback = null;
        
        // Store the original camera view.
        mCamStartViewPoint = new VgIViewPoint( mVgApplication.editEngine().editCamera().getViewpoint() );
        
        // Store original LOD and load factors
        VgLayerVector lLayers = mVgApplication.editEngine().editLayerManager().editLayers();
        for (int iLayer=0; iLayer < lLayers.size(); ++iLayer)
        {
            VgLayerRefPtr lLayer = lLayers.get(iLayer);
            mLoadFactor.put(lLayer.getName(), lLayer.getLoadFactor() );
            mLODFactor.put(lLayer.getName(), lLayer.getLODFactor() );
        }
    }
    
    
    protected void setDefaultStackParams()
    {
        // Default stack center position is the root of the scene.
        VgPosition lStackCenterPos = new VgPosition( mVgApplication.editEngine().getPositionToolbox().getSceneSRS() );
        
        float lDatasetSize = 700.0f; // Default stack size that works well for map generic.
        
        // Calculate the stack center based on the dataset limits within vg_config.xml
        VgIDatabaseDatasetDescriptor lDescriptor = mVgApplication.editEngine().editDatabase().getCurrentDatasetDescriptor();
        if(null != lDescriptor)
        {
            // Calculate real stack diameter
            float lDatasetSizeTemp = (float) mVgApplication.editEngine().getPositionToolbox().computeDistance(lDescriptor.getMMinimum(), lDescriptor.getMMaximum());
            // If the dataset limits have been set correctly in the configuration file
            if (lDatasetSizeTemp > 1e-3)
            {
                // Then update the dataset size
                lDatasetSize = lDatasetSizeTemp;
                lStackCenterPos.setMSRS(lDescriptor.getMMaximum().getMSRS());
                // And the stack center by default should be in the center of the dataset limits.
                lStackCenterPos.setMXOrLongitude((lDescriptor.getMMinimum().getMXOrLongitude() + lDescriptor.getMMaximum().getMXOrLongitude()) / 2);
                lStackCenterPos.setMYOrLatitude((lDescriptor.getMMinimum().getMYOrLatitude() + lDescriptor.getMMaximum().getMYOrLatitude()) / 2);
                lStackCenterPos.setMZOrAltitude((lDescriptor.getMMinimum().getMZOrAltitude() + lDescriptor.getMMaximum().getMZOrAltitude()) / 2);
            }
        }
        
        setParam(VgMyConfigurableParam.eLayerMaxSize, lDatasetSize);
        setStackCenterPosition(lStackCenterPos);
        
        // Set the default heading to be that from the initial camera view (taken
        // from the configuration file)
        float lStackViewHeading = (float) mVgApplication.editEngine().editCamera().getViewpoint().getMHeading();
        setParam(VgMyConfigurableParam.eStackViewHeading, lStackViewHeading);
                
        
        // Static parameters
        setParam(VgMyConfigurableParam.eFarAwayHeight, 1000);
        setParam(VgMyConfigurableParam.eStackViewPitch, -30);
        // Trigger threshold parameters
        setParam(VgMyConfigurableParam.eChangeLayerTriggerThreshold, 0.1);
        // Animation timers
        setParam(VgMyConfigurableParam.eAnimateToDetailCameraDuration, 1.0);
        setParam(VgMyConfigurableParam.eAnimateToGlobalCameraDuration, 1.5);
        setParam(VgMyConfigurableParam.eAnimateToGlobalLayerDuration, 1.5);
        setParam(VgMyConfigurableParam.eAnimateToDetailLayerDuration, 1.0);
        setParam(VgMyConfigurableParam.eAnimateChangeOfLayerDuration, 0.5);
        setParam(VgMyConfigurableParam.eAnimateCancelPinchDuration, 0.3);
        setParam(VgMyConfigurableParam.eAnimateCancelDragDuration, 0.3);
        setParam(VgMyConfigurableParam.eAnimateMaxViewPointDuration, 3.0);
        
        setParam(VgMyConfigurableParam.eStackActiveLayerAngle, 0.0f);
        setParam(VgMyConfigurableParam.eStackNonActiveLayerAngle, 0.0f);
    }
    
    
    public void updateManipulatorForGlobalView(boolean pIsGlobalView)
    {
        if (pIsGlobalView)
        {
            mVgApplication.editManipulatorManager().selectManipulator("simpleGesture");
            onSelectorReady();
        }
        else
        {
            mVgApplication.editManipulatorManager().selectManipulator("2D");
            onLayerSelected();
        }
        
        if (null != mLayerUpdateListener)
        {
            boolean lDoesChangeFromGlobalToDetailed = !pIsGlobalView;
            mLayerUpdateListener.viewDidChange(this, lDoesChangeFromGlobalToDetailed);
        }
    }
    
    
    public boolean isGlobalView()
    {
        return mIsLayerStackDisplayed;
    }
    
    
    public void switchToGlobalView(boolean pIsAnimated)
    {
        if (mIsLayerStackDisplayed && mIsViewModeInitialized)
        {
            return;
        }

        if (null != mLayerUpdateListener)
        {
            mLayerUpdateListener.viewWillChange((VgMyLayerAndCameraHandler)this, false);
        }
        
        // Store the current camera view. It will be restored when leaving the stack view.
        // REQUIREMENT: Orientation floor level same as orientation global view, set to false
        boolean lSaveDetailedViewpoint = false;
        if (lSaveDetailedViewpoint)
        {
            mCamStartViewPoint = mVgApplication.editEngine().editCamera().getViewpoint();
        }
        

        // Store the current camera view. It will be restored when leaving the stack view.
        mCamStartViewPoint = new VgIViewPoint( mVgApplication.editEngine().editCamera().getViewpoint() );

        VgIViewPoint lViewPoint = getStackViewPoint();
        animateCameraToViewPoint(lViewPoint, (float)getParam(VgMyConfigurableParam.eAnimateToGlobalCameraDuration), pIsAnimated);
        
        animateLayersFromCloseToStackView(eFromToViewEnum.eFromDetailedToStackView, (float)getParam(VgMyConfigurableParam.eAnimateToGlobalLayerDuration), pIsAnimated);
        
        if(!pIsAnimated)
        {
            updateManipulatorForGlobalView(true);
        }
        
        if (!mIsViewModeInitialized)
        {
            mIsViewModeInitialized = true;
        }
        
        mIsLayerStackDisplayed = true;
    }


    public void switchToDetailedView(boolean pIsAnimated)
    {
        if ((!mIsLayerStackDisplayed) && mIsViewModeInitialized)
        {
            return;
        }
        
        if (null != mLayerUpdateListener)
        {
            mLayerUpdateListener.viewWillChange(this, true);
        }

        // Note : camera animation length must be <= layer animation length due to the manipulator change at the end of layers animation.
        animateCameraToViewPoint(mCamStartViewPoint, (float)getParam(VgMyConfigurableParam.eAnimateToDetailCameraDuration), pIsAnimated);
        
        animateLayersFromCloseToStackView(eFromToViewEnum.eFromStackToDetailedView, (float)getParam(VgMyConfigurableParam.eAnimateToDetailLayerDuration), pIsAnimated);

        if(!pIsAnimated)
        {
            updateManipulatorForGlobalView(false);
        }
        
        if (!mIsViewModeInitialized)
        {
            mIsViewModeInitialized = true;
        }
        
        mIsLayerStackDisplayed = false;
    }

    public String getFocusedLayerName()
    {
        VgLayerVector lLayers = mVgApplication.editEngine().editLayerManager().editLayers();
        return lLayers.get((int) mCurrentLayerIndex).getName();
    }

    public long getNumberOfLayers()
    {
        VgLayerVector lLayers = mVgApplication.editEngine().editLayerManager().editLayers();
        return lLayers.size();
    }


    public boolean getLayerName(long pLayerIndex, String pLayerNameOut)
    {
        VgLayerVector lLayers = mVgApplication.editEngine().editLayerManager().editLayers();
        if (pLayerIndex < lLayers.size())
        {
            pLayerNameOut = lLayers.get((int)pLayerIndex).getName();
            return true;
        }
        else
        {
            return false;
        }
    }

    
    public void gotoLayer(String pLayerName, boolean pIsAnimated)
    {
        VgLayerVector lLayers = mVgApplication.editEngine().editLayerManager().editLayers();
        boolean lIsFound = false;
        int lLayerIndex = 0;
        for(; (lIsFound == false) && (lLayerIndex < lLayers.size() ); ++lLayerIndex)
        {
            String lLayerName = lLayers.get(lLayerIndex).getName(); 
            if(true == lLayerName.contentEquals(pLayerName))
            {
                lIsFound = true;
                break;
            }
        }
        
        if (lIsFound)
        {
            gotoLayer(lLayerIndex, pIsAnimated);
        }
    }


    public void gotoLayer(long pLayerIndex, boolean pIsAnimated)
    {
        VgLayerVector lLayers = mVgApplication.editEngine().editLayerManager().editLayers();
        if( (pLayerIndex < 0) || 
            pLayerIndex >= lLayers.size() || 
            ( (pLayerIndex == mCurrentLayerIndex) && (true == mIsLayerInitialized) ) )
        {
            return;
        }

        if (null != mLayerUpdateListener)
        {
            mLayerUpdateListener.layerWillChangeFrom(this, lLayers.get((int)mCurrentLayerIndex).getName(), lLayers.get((int)pLayerIndex).getName() );
        }

        if (mIsLayerStackDisplayed)
        {
            gotoLayerInGlobalView(pLayerIndex, pIsAnimated);
        }
        else
        {
            gotoLayerInDetailedView(pLayerIndex, pIsAnimated);
        }

        mCurrentLayerIndex = pLayerIndex;
        mIsLayerInitialized = true;     
    }

    public void gotoLayerInGlobalView(long pLayerIndex, boolean pIsAnimated)
    {
        if (mIsLayerStackDisplayed)
        {
            VgLayerVector lLayers = mVgApplication.editEngine().editLayerManager().editLayers();
            if (pLayerIndex >= lLayers.size() || ((pLayerIndex == mCurrentLayerIndex) && (true == mIsLayerInitialized)) ) 
            {
                return;
            }
            VgIAnimationCallbackRefPtr lAnimCallback = null;
            // Animates each layer to it's new position
            VgPosition lLayerStartPos = new VgPosition();
            VgPosition lLayerEndPos = new VgPosition();
        
            // All layers are already visible. Moves layers so that pLayerIndex is centered on the view.
            for (int iLayer=0; iLayer < lLayers.size(); ++iLayer)
            {
                VgLayerRefPtr lLayer = lLayers.get(iLayer);
                
                float lStartAngle = (float)getParam(VgMyConfigurableParam.eStackNonActiveLayerAngle);
                float lEndAngle = (float)getParam(VgMyConfigurableParam.eStackNonActiveLayerAngle);
                
                lLayerStartPos = lLayer.getPosition();
                
                boolean lIsHostVisibleForLayer = false;
                if(iLayer == pLayerIndex)
                {
                    lIsHostVisibleForLayer = true;
                    lEndAngle = (float)getParam(VgMyConfigurableParam.eStackActiveLayerAngle);
                }
                if (iLayer == mCurrentLayerIndex)
                {
                    lStartAngle = (float)getParam(VgMyConfigurableParam.eStackActiveLayerAngle);
                    lEndAngle = (float)getParam(VgMyConfigurableParam.eStackNonActiveLayerAngle);
                }
                if (mCurrentLayerIndex == pLayerIndex)
                {
                    lStartAngle = lEndAngle = (float)getParam(VgMyConfigurableParam.eStackActiveLayerAngle);
                }
                
                
                lLayer.setHostedVisible(lIsHostVisibleForLayer);
                
                lLayer.setVisible(true);
                
                // Note: pLayerIndex will eventually be the current layer.
                lLayerEndPos = getPositionForLayerInGlobalView(iLayer, (int) pLayerIndex);
                
                if (pIsAnimated)
                {
                    lAnimCallback = new VgIAnimationCallbackRefPtr(new StopAnimationCallback(new VgSpatialRefPtr(lLayer.get()), null, null));
                    animateLayerToPositionAndRotation(lLayer, lLayerStartPos, lLayerEndPos, lAnimCallback, (float)getParam(VgMyConfigurableParam.eAnimateChangeOfLayerDuration), lStartAngle, lEndAngle);
                }
                else
                {
                    lLayer.setPosition(lLayerEndPos);
                }
                
            }
        }
     
    }

    public void gotoLayerInDetailedView(long pLayerIndex, boolean pIsAnimated)
    {
        if(!mIsLayerStackDisplayed)
        {
            VgLayerVector lLayers = mVgApplication.editEngine().editLayerManager().editLayers();
            
            VgIAnimationCallbackRefPtr lAnimCallback = null;
            
            // Only the current layer is visible.
            // Set visible all layers between the current one and the target.
            for (long iLayer = Math.min(mCurrentLayerIndex, pLayerIndex), iLayerEnd = Math.max(mCurrentLayerIndex, pLayerIndex)  ; iLayer <= iLayerEnd ; ++iLayer)
            {
                VgLayerRefPtr lLayer = lLayers.get((int)iLayer);
                VgPosition lLayerStartPos = new VgPosition(lLayer.getPosition());
                VgPosition lLayerEndPos = new VgPosition();
                
                
                if (((iLayer < pLayerIndex && iLayer >= mCurrentLayerIndex) || (iLayer > pLayerIndex && iLayer <= mCurrentLayerIndex)))
                {
                    lLayer.setVisible(true);
                    lLayer.setHostedVisible(false);
                    
                    if (pIsAnimated)
                    {
                        lAnimCallback = new VgIAnimationCallbackRefPtr(new LayerHideCallback(lLayer));
                    }
                }
                // no else here. Other layers are already hidden.
                
                if (iLayer != pLayerIndex)
                {
                    lLayer.setLODFactor((float) 1e-3);
                    lLayer.setLoadFactor((float) 1e-3);
                }
                else
                {
                    lLayer.setVisible(true);
                    lLayer.setHostedVisible(true);
                    lLayer.setLODFactor(mLODFactor.get(lLayer.getName()));
                    lLayer.setLoadFactor(mLoadFactor.get(lLayer.getName()));
                    
                    if (pIsAnimated)
                    {
                        lAnimCallback = new VgIAnimationCallbackRefPtr(new StopAnimationCallback(new VgSpatialRefPtr(lLayer.get()), null, null));
                    }
                }
                
                // Note: pLayerIndex will eventually be the current layer.
                lLayerEndPos = getPositionForLayerInDetailedView(iLayer, pLayerIndex);

                if (pIsAnimated)
                {
                    animateLayerToPositionAndRotation(lLayer, lLayerStartPos, lLayerEndPos, lAnimCallback, (float) getParam(VgMyConfigurableParam.eAnimateChangeOfLayerDuration), 0.0f,60.0f);
                }
                else
                {
                    if (iLayer == pLayerIndex)
                    {
                        lLayer.setPosition(lLayerEndPos);
                    }
                    else
                    {
                        lLayer.setVisible(false);
                        lLayer.setHostedVisible(false);
                    }       
                }
            }
        }
    }

    public VgPosition getPositionForLayerInGlobalView(long pLayerIndex, long pFocusedLayer)
    {
        VgPosition lLayerPos = new VgPosition(mVgApplication.editEngine().getPositionToolbox().getSceneSRS());
        
        // The distance from the focused layer.
        float lZDistanceFromFocusedLayer = 0.0f;
        
        if (pLayerIndex != pFocusedLayer)
        {
             lZDistanceFromFocusedLayer = (float) (getParam(VgMyConfigurableParam.eLayerDistanceFromCurrent) + (getParam(VgMyConfigurableParam.eLayerDistance) * ( Math.abs(((float)pLayerIndex - (float)pFocusedLayer) - 1.0f))));
            
            if(pLayerIndex > pFocusedLayer)
            {
                
                // Move the layer away from the focused layer, in a direction perpendicular to the camera, starting from the stack center
                float lHeading = (float) (getParam(VgMyConfigurableParam.eStackViewHeading) + 180.0f);
                float lPitch = (float) ((-1.0f * getParam(VgMyConfigurableParam.eStackViewPitch)) - 90.0f);
                lLayerPos = mVgApplication.editEngine().getPositionToolbox().offsetPosition(lLayerPos, lHeading, lPitch, -lZDistanceFromFocusedLayer);
            }
            else
            {
                lLayerPos.setMZOrAltitude(-lZDistanceFromFocusedLayer);
            }
        }
        else
        {
            lLayerPos.setMZOrAltitude(lZDistanceFromFocusedLayer);
        }
        
        return lLayerPos;
    }


    public VgPosition getPositionForLayerInDetailedView(long pLayerIndex, long pFocusedLayer)
    {   
        // Create the scene root position
        VgPosition lSceneRoot = new VgPosition( mVgApplication.editEngine().getPositionToolbox().getSceneSRS() );
        
        // Set the layer to the scene root position
        VgPosition lLayerPos = lSceneRoot;
        
        // Update the altitude in relation to the layer.
        if (pLayerIndex != pFocusedLayer)
        {
             float lAltitude = (pLayerIndex < pFocusedLayer ? (float)-getParam(VgMyConfigurableParam.eFarAwayHeight) : (float)getParam(VgMyConfigurableParam.eFarAwayHeight));
            lLayerPos.setMZOrAltitude(lAltitude);
        }
        else
        {
            lLayerPos.setMZOrAltitude(0);
        }
        return lLayerPos;
    }    
    

    public void gotoViewpoint(VgIViewPoint pViewPoint, String pLayerName, boolean pIsAnimated)
    {
        // Note: chaining animations currently not implemented.  Below the algorithm. makes 
        // a choice of which camera movement to animate.
        
        // If global view
        if(isGlobalView()) 
        {
            gotoLayer(pLayerName, pIsAnimated);
        }
        // Else detailed view
        else 
        {
            VgLayerRefPtr lCurrentLayer = mVgApplication.editEngine().editLayerManager().editLayers().get((int)getCurrentLayerIndex() );
            String lCurrentLayerName = lCurrentLayer.getName();
            
            VgPositionToolbox lPositionToolbox = mVgApplication.editEngine().getPositionToolbox();
            
         // Don't animate zero-length displacements. This would cause numeric instability.
            if (lPositionToolbox.computeDistance(pViewPoint.getMPosition(), mVgApplication.editEngine().editCamera().getPosition()) < 1e-3) 
            {
                // The layer is the current layer
                if(!lCurrentLayerName.equals(pLayerName) || !mIsLayerInitialized) 
                {
                    // Change camera position and then animate to layer.
                    gotoLayer(pLayerName, pIsAnimated);
                }
            } 
            else 
            {
                // Compute the duration.
                VgPositionVector lPosVec = new VgPositionVector();
                lPosVec.add(pViewPoint.getMPosition());
                lPosVec.add(mVgApplication.editEngine().editCamera().getPosition());
                
                double lRouteLength = lPositionToolbox.computeDistance(lPosVec);
                double lSpeed = 10.0;
                float lDuration = (float) Math.min((lRouteLength / lSpeed), getParam(VgMyConfigurableParam.eAnimateMaxViewPointDuration));
    
                if(lCurrentLayerName.equals(pLayerName) && mIsLayerInitialized)
                {
                    // Animate to layer.
                    animateCameraToViewPoint(pViewPoint, lDuration, pIsAnimated);
                }
                // And the layer does change
                else 
                {
                    // Change camera position and then animate to layer.
                    animateCameraToViewPoint(pViewPoint, lDuration, false);
                    gotoLayer(pLayerName, pIsAnimated);
                }                
            }
        }
    }


    public void gotoLookAtPosition(VgPosition pPosition, String pLayerName, boolean pIsAnimated)
    {
        VgLayerRefPtr lLayer = mVgApplication.editEngine().editLayerManager().editLayer(pLayerName);
        if (null == lLayer)
        {
            return;
        }

        VgICamera lCamera = mVgApplication.editEngine().editCamera();
        VgPositionToolbox lPositionToolbox = mVgApplication.editEngine().getPositionToolbox();
        
        VgPosition lNewPosition = new VgPosition(pPosition);
        lNewPosition.setMZOrAltitude(0);
        
        // We must be sure that the final position is expressed in the Scene SRS.
        lPositionToolbox.convert(lNewPosition, new VgSRSConstRefPtr(lCamera.getPosition().getMSRS()));
                
        VgPositionVector lPositions = new VgPositionVector();
        lPositions.add(lNewPosition);
        VgIViewPoint lViewPointEnd = lCamera.getViewpointFromPositions(lPositions, 0, 0, 0, 0);

        gotoViewpoint(lViewPointEnd, pLayerName, pIsAnimated);
    }
    
    
    public void animateLayersFromCloseToStackView(eFromToViewEnum pDirection, float pDuration, boolean pIsAnimated)
    {
        // we want pFromCloseToStackView to be:
        // true:  eFromDetailedToStackView,
        // true:  eFromGlobalToGlobaView // Used by cancel drag.
        // false: eFromStackToDetailedView
        boolean pFromCloseToStackView = (pDirection != eFromToViewEnum.eFromStackToDetailedView) ? true : false;

        VgLayerVector lLayers = mVgApplication.editEngine().editLayerManager().editLayers();

        for (int i=0; i < lLayers.size(); ++i)
        {
            VgLayerRefPtr lLayer = lLayers.get(i);
            VgIAnimationCallbackRefPtr lCallback = null;
            
            VgPosition lLayerStartPos = new VgPosition(lLayer.getPosition());
            VgPosition lLayerEndPos = new VgPosition();

            if (!mIsLayerStackDisplayed)
            {
                lLayer.setLODFactor((float) 1e-3);
                lLayer.setLoadFactor((float) 1e-3);
                lLayer.setVisible(true);
            }
            else if (pFromCloseToStackView)
            {
                if (pIsAnimated)
                {
                    lCallback = new VgIAnimationCallbackRefPtr(new StopAnimationCallback(new VgSpatialRefPtr(lLayer.get()), null, null));
                }
            }
            
            if (i != mCurrentLayerIndex)
            {
                lLayer.setHostedVisible(false);
                
                if (pFromCloseToStackView)
                {
                    if (!mIsLayerStackDisplayed)
                    {
                        if (pIsAnimated)
                        {
                            lCallback = new VgIAnimationCallbackRefPtr(new StopAnimationCallback(new VgSpatialRefPtr(lLayer.get()), null, null));
                        }
                    }
                }
                else
                {
                    if (pIsAnimated)
                    {
                        lCallback = new VgIAnimationCallbackRefPtr(new LayerHideCallback(lLayer));
                    }
                }
            }
            else
            {
                lLayer.setHostedVisible(true);
                if (!pFromCloseToStackView)
                {
                    lLayer.setLODFactor(mLODFactor.get(lLayer.getName()));
                    lLayer.setLoadFactor(mLoadFactor.get(lLayer.getName()));
                }
                
                if (!mIsLayerStackDisplayed  || !pFromCloseToStackView)
                {
                    if (pIsAnimated)
                    {
                        lCallback = new VgIAnimationCallbackRefPtr(new StopAnimationCallback(new VgSpatialRefPtr(lLayer.get()), mVgApplication.editManipulatorManager(), this));
                    }
                }
            }
            
            // Get end point position for layer.
            if(pFromCloseToStackView)
            {
                lLayerEndPos = getPositionForLayerInGlobalView(i, mCurrentLayerIndex);
            }
            else
            {
                lLayerEndPos = getPositionForLayerInDetailedView(i, mCurrentLayerIndex);
            }
            
            
            if (pIsAnimated)
            {
               // animateLayerToPosition(lLayer, lLayerStartPos, lLayerEndPos, lCallback, pDuration);
                float lStartAngle;
                float lEndAngle;
                
                if (pFromCloseToStackView)
                {
                    lStartAngle = (float)getParam(VgMyConfigurableParam.eStackNonActiveLayerAngle);
                    lEndAngle = (i== mCurrentLayerIndex) ? (float)getParam(VgMyConfigurableParam.eStackActiveLayerAngle) : (float)getParam(VgMyConfigurableParam.eStackNonActiveLayerAngle);
                    
                    // in the case we are in the same layer, we don't move it.
                    if (mCurrentLayerIndex == i && pDirection == eFromToViewEnum.eFromGlobalToGlobaView)
                    {
                        lStartAngle = lEndAngle = (float)getParam(VgMyConfigurableParam.eStackActiveLayerAngle);
                    }
                }
                else
                {
                    lStartAngle = (i== mCurrentLayerIndex) ? (float)getParam(VgMyConfigurableParam.eStackActiveLayerAngle) : (float)getParam(VgMyConfigurableParam.eStackNonActiveLayerAngle);
                    // on the detailed view the end angle is always 0.0f
                    lEndAngle = 0.0f;
                }

                
                animateLayerToPositionAndRotation(lLayer, lLayerStartPos, lLayerEndPos, lCallback, (float)pDuration,lStartAngle,lEndAngle);   
            }
            else
            {
                if (i != mCurrentLayerIndex)
                {
                    lLayer.setHostedVisible(false);
                    if (!pFromCloseToStackView)
                    {
                        lLayer.setVisible(false);
                    }
                }
                else
                {
                    lLayer.setVisible(true);
                    lLayer.setHostedVisible(true);
                }
                lLayer.setPosition(lLayerEndPos);
            }
        }
    }

    
    public void animateLayerToPositionAndRotation(VgLayerRefPtr pLayer,
                                           VgPosition pStartPos,
                                           VgPosition pEndPos,
                                           VgIAnimationCallbackRefPtr pCallback,
                                           float pDuration,
                                           float pStartAngle,
                                           float pEndAngle)
    {
        VgAnimationDescriptorRefPtr lLayerAnimDesc = VgAnimationDescriptor.create();
        lLayerAnimDesc.setMDuration(pDuration);
        VgVectorInterpolationFunctorDescriptorRefPtr lLayerPosDescr = VgVectorInterpolationFunctorDescriptor.create();
        lLayerAnimDesc.getMFunctorDescriptors().set(VgAnimationChannels.getMscPositionChannel(), new VgFunctorDescriptorRefPtr(lLayerPosDescr.get()));
        lLayerAnimDesc.setMCallback(pCallback);
        lLayerPosDescr.setMStartPosition(pStartPos);
        lLayerPosDescr.setMEndPosition(pEndPos);
        
        
        // we apply the rotation functor if we have some rotation on an
        // active or non-active layer.
        // we don't use the parameter pStartAngle/pEndAngle,
        // because if we are using rotation these may be used with value
        // 0 to put the layer back in its original orientation.
        if (getParam(VgMyConfigurableParam.eStackActiveLayerAngle) != 0.0f || getParam(VgMyConfigurableParam.eStackNonActiveLayerAngle) != 0.0f)
        {
            VgAxialRotationQuaternionFunctorDescriptorRefPtr lLayerRotationDescr = VgAxialRotationQuaternionFunctorDescriptor.create();
            lLayerAnimDesc.getMFunctorDescriptors().set(VgAnimationChannels.getMscOrientationChannel(), new VgFunctorDescriptorRefPtr(lLayerRotationDescr.get()));
        
            double lCurrentHeadingDegrees = getParam(VgMyConfigurableParam.eStackViewHeading);
            double lHeadingInRad = (lCurrentHeadingDegrees+90.0) * Math.PI / 180.0;

            float[] lValue = new float[3];
            lValue[0] = (float) Math.sin(lHeadingInRad);
            lValue[1] = (float) Math.cos(lHeadingInRad);
            lValue[2] = (float) 0.0f;
            lLayerRotationDescr.setMAxis(lValue);
        
            lLayerRotationDescr.setMStartAngle(-pStartAngle);
            lLayerRotationDescr.setMEndAngle(-pEndAngle);
            lLayerRotationDescr.setMCubic(false);
        }
        
        VgAnimationRefPtr lLayAnim = mVgApplication.editEngine().editInstanceFactory().instantiate(lLayerAnimDesc);
        pLayer.setAnimation("",lLayAnim);
        lLayAnim.start();
    }    
    
    public VgIViewPoint getStackViewPoint()
    {
        mCameraGlobalViewPoint.setMPosition(mVgApplication.editEngine().getPositionToolbox().offsetPosition(mStackCenter,
                                                                                                  getParam(VgMyConfigurableParam.eStackViewHeading),
                                                                                                  getParam(VgMyConfigurableParam.eStackViewPitch),
                                                                                                  -getParam(VgMyConfigurableParam.eStackViewDistance) ) );
        
        mCameraGlobalViewPoint.setMHeading( getParam(VgMyConfigurableParam.eStackViewHeading) );
        
        mCameraGlobalViewPoint.setMPitch( getParam(VgMyConfigurableParam.eStackViewPitch) );
        
        return mCameraGlobalViewPoint;
    }
    
    public void animateCameraToViewPoint(VgIViewPoint pViewPoint, float pDuration, boolean pIsAnimated)
    {
        if(pIsAnimated)
        {
            VgIViewPoint lCameraViewpoint = mVgApplication.editEngine().editCamera().getViewpoint();
            
            VgVectorInterpolationFunctorDescriptorRefPtr lPosDescr = VgVectorInterpolationFunctorDescriptor.create();
            lPosDescr.setMStartPosition(lCameraViewpoint.getMPosition());
            lPosDescr.setMEndPosition(pViewPoint.getMPosition());
            lPosDescr.setMCubic(true);
            
            VgAnimationDescriptorRefPtr lAnimDescr = VgAnimationDescriptor.create();
            lAnimDescr.setMDuration(pDuration);
            
            lAnimDescr.getMFunctorDescriptors().set(VgAnimationChannels.getMscPositionChannel(), new VgFunctorDescriptorRefPtr(lPosDescr.get()));
            
            mCameraCallback = new VgIAnimationCallbackRefPtr(new StopAnimationCallback(null, mVgApplication.editManipulatorManager(), this));
            lAnimDescr.setMCallback(mCameraCallback);
            
            VgQuaternionInterpolationFunctorDescriptorRefPtr lOrientDesc = VgQuaternionInterpolationFunctorDescriptor.create();
            lOrientDesc.setMCubic(true);
            lOrientDesc.getMStartOrientation().setMAzimuth((float) lCameraViewpoint.getMHeading());
            lOrientDesc.getMStartOrientation().setMPitch((float) lCameraViewpoint.getMPitch());
            lOrientDesc.getMStartOrientation().setMRoll((float) 0.0);
            lOrientDesc.getMEndOrientation().setMAzimuth((float) pViewPoint.getMHeading());
            lOrientDesc.getMEndOrientation().setMPitch((float) pViewPoint.getMPitch());
            lOrientDesc.getMEndOrientation().setMRoll((float) 0.0);
            
            lAnimDescr.getMFunctorDescriptors().set(VgAnimationChannels.getMscOrientationChannel(), new VgFunctorDescriptorRefPtr(lOrientDesc.get()));
            
            VgAnimationRefPtr lCamAnim = mVgApplication.editEngine().editInstanceFactory().instantiate(lAnimDescr);
            mVgApplication.editEngine().editAnimationManager().setCameraAnimation(lCamAnim);
            mVgApplication.editManipulatorManager().selectManipulator("animation");
            lCamAnim.start();
        }
        else
        {
             if (isGlobalView())
                {
                    mVgApplication.editManipulatorManager().selectManipulator("simpleGesture");
                }
                else
                {
                    mVgApplication.editManipulatorManager().selectManipulator("2D");
                }
            mVgApplication.editEngine().editCamera().setViewpoint(pViewPoint);
        }        
    }    
  
    
    public VgPosition getCameraPosition()
    {
        return mCamStartViewPoint.getMPosition(); 
    }

    public void onLayerSelected()
    {}

    public void onSelectorReady()
    {}
    
    long getCurrentLayerIndex()
    {
        return mCurrentLayerIndex;
    }
    
    protected boolean mRefreshParameterOnce = false;   
    public void refreshParameters(long pWidth, long pHeight)
    {
        /*
         * FIELD OF VIEW MANAGEMENT
         * The field of view of the VisioDevKit is adaptative, such that when you change the
         * size of the view, the field of view changes so the object does not appear to change size.
         * in SDK examples before and including 2.0.8409.8434
         * The field of view was set to a "reference screen", thus on very large screens
         * or screens with very high resolution, the map may appear to be very small and 
         * potentially distorted.
         * Using the lNewFieldOfViewBehaviour, we set the horizontal field of view to a fixed
         * value ONCE regardless of the screen size, this makes it predictable what the user
         * will see regardless of their screen resolution.
         * It is important to do it once, because if the screen sizes in portrait and landscape
         * are not exactly the same, slight popping may be visible after the rotation.
         */
        final boolean lNewFieldOfViewBehaviour = true;
        
        if (lNewFieldOfViewBehaviour && !mRefreshParameterOnce)
        {
            VgICamera lCamera = mVgApplication.editEngine().editCamera();

            double lFovInPortrait = 86.199999; // Field of View for portrait mode
            if (pHeight > pWidth)
            {
                lCamera.setFovX(lFovInPortrait);
            }
            else
            {
                // Landscape case
                final double DEG_TO_RAD = .0174532925199432958;
                final double RAD_TO_DEG = 57.2957795130823207758;
                
                double lTanFOVPerPixel = Math.tan(0.5 * lFovInPortrait * DEG_TO_RAD ) / (pHeight);
                
                
                /*
                 * Recompute the field of view such that in landscape the objects have the same size on the screen, thus when you rotate the screen into landscape you will not have any popping and you will have some extra space on the sides
                 */
                double lFovInLandscape = Math.atan(((float)(  lTanFOVPerPixel  * pWidth) ) ) *2.0*RAD_TO_DEG;
                
                /*
                 * Uncommenting the code below will make the horizontal field of view the same
                 *  in both landscape and portrait, thus horizontally, if something touches both borders of the screen, it will touch it in both landscape and portrait.
                 */
                // lFovInLandscape = lFovInPortrait
                lCamera.setFovX(lFovInLandscape);
            }
            mRefreshParameterOnce = true;
        }
        
        mFloorSelectorManipulator.setScreenSize(pWidth, pHeight);
        calculateDynamicStackParams();
        refreshStackView();
    }

    public void refreshStackView()
    {
        // As the parameters are to configure the global view, the global view must be refreshed.
        if (isGlobalView())
        {           
            VgIViewPoint lViewPoint = getStackViewPoint();
            animateCameraToViewPoint(lViewPoint, 0.0f, false);
            
            animateLayersFromCloseToStackView(eFromToViewEnum.eFromDetailedToStackView, 0.0f, false);
        } 
    }

    // FOV refreshers course...
    // http://stackoverflow.com/questions/4427662/whats-the-relationship-between-field-of-view-and-lens-length
    //
    protected void calculateDynamicStackParams()
    {
        double lDatasetDiameter = getParam(VgMyConfigurableParam.eLayerMaxSize);
        
        double lFovXRadians = mVgApplication.editEngine().editCamera().getFovX() * Math.PI / 180.0;
        double lTanHalfFovX = Math.tan(lFovXRadians/2.0);
        double lFovYRadians = mVgApplication.editEngine().editCamera().getFovY() * Math.PI / 180.0;
        double lTanHalfFovY = Math.tan(lFovYRadians/2.0);
        
        // Represents the distance the camera should be away from the scene to fit the layer width.
        double lStackViewDistance = ( (lDatasetDiameter / 2 ) / lTanHalfFovX);
        // A ratio to ensure layer boundaries have some buffer between them and the edge of the view,
        // essentially moves the camera back away from the layers.
        double lStackViewDistanceBufferRatio = 0.8f;
        setParam(VgMyConfigurableParam.eStackViewDistance, (lStackViewDistance * lStackViewDistanceBufferRatio));
        // The vertical height of the camera view
        double lVerticalHeight = ( (lTanHalfFovY * getParam(VgMyConfigurableParam.eStackViewDistance)) * 2 );
        
        int lNumOfLayers = (int)mVgApplication.editEngine().editLayerManager().editLayers().size();
        double lLayerDistanceFromCurrent = lVerticalHeight / (1 + lNumOfLayers);
        setParam(VgMyConfigurableParam.eLayerDistanceFromCurrent, lLayerDistanceFromCurrent);
        
        // Reducing eLayerDistance creates extra buffer space at the bottom and top of the screen,
        // more so with bundles with lots of layers.
        double lLayerDistanceBufferRatio = 0.33f;
        double lLayerDistance = (getParam(VgMyConfigurableParam.eLayerDistanceFromCurrent) * lLayerDistanceBufferRatio);
        setParam(VgMyConfigurableParam.eLayerDistance, lLayerDistance);     
    }


    public void setStackCenterPosition(VgPosition pCenterPos)
    {
        VgPositionToolbox lPosToolbox  = mVgApplication.editEngine().getPositionToolbox();
        mStackCenter = pCenterPos;
        // Convert stack center to have the same spatial reference as the scene        
        lPosToolbox.convert(mStackCenter, lPosToolbox.getSceneSRS());
    }


    public VgPosition getStackCenter()
    {
        return mStackCenter;
    }

    public void setParam(VgMyConfigurableParam pParam, double pDouble)
    {
        if(pParam.ordinal() < VgMyConfigurableParam.eMaxDoubleParams.ordinal())
        {
            mParam[pParam.ordinal()] = pDouble;
        }
        
        if(pParam == VgMyConfigurableParam.eLayerMaxSize)
        {
            // Dynamically calculate some configurable stack parameters based on the new eLayerMaxSize 
            calculateDynamicStackParams();
        }
    }

    public double getParam(VgMyConfigurableParam pParam)
    {
        double lRetVal = 0.0;
        if(pParam.ordinal() < VgMyConfigurableParam.eMaxDoubleParams.ordinal())
        {
            lRetVal = mParam[pParam.ordinal()];
        }
        return lRetVal;
    }


    @Override
    public void release()
    {
        // Remove any animation still registered on the layers
        VgLayerVector lLayers = mVgApplication.editEngine().editLayerManager().editLayers();
        for (int i = 0; i < lLayers.size(); ++i)
        {
            lLayers.get(i).setAnimation("",VgAnimationRefPtr.getNull());
        }
        if (mSimpleGestureManipulator != null)
        {
            mSimpleGestureManipulator.setListener(VgISimpleGestureManipulatorListenerRefPtr.getNull());
            mSimpleGestureManipulator = null;
        }
        
        if (mFloorSelectorManipulatorRefPtr != null && mFloorSelectorManipulatorRefPtr.isValid())
        {
            mFloorSelectorManipulatorRefPtr.set(null);
            mFloorSelectorManipulator = null;
        }
        if (mCameraCallback != null &&mCameraCallback.isValid())
        {
            mCameraCallback.set(null);
        }
        mVgApplication.editEngine().editAnimationManager().setCameraAnimation(VgAnimationRefPtr.getNull());
    }
}

./Common/Makefiles/Android/src/com/visioglobe/VisioSample/Interfaces/VgMyAnchoredDisplay.java

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

package com.visioglobe.VisioSample.Interfaces;

import com.visioglobe.libVisioDevKit.VgPosition;

public interface VgMyAnchoredDisplay extends VgMyDisplayable
{

    public void setAnchorPosition(String pPlaceID, VgPosition pPosition);

    public void release();
}

./Common/Makefiles/Android/src/com/visioglobe/VisioSample/Interfaces/VgMyDisplayable.java

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

package com.visioglobe.VisioSample.Interfaces;

public interface VgMyDisplayable
{

    public void show();

    public void hide();

    public boolean isVisible();
}

./Common/Makefiles/Android/src/com/visioglobe/VisioSample/Interfaces/VgMyInstructionDisplay.java

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

package com.visioglobe.VisioSample.Interfaces;

import com.visioglobe.libVisioDevKit.VgINavigationConstRefPtr;


public interface VgMyInstructionDisplay extends VgMyDisplayable
{
    void updateWithInstruction(VgINavigationConstRefPtr pNavigation, long pIndex);

    void clear();

    void release();

}

./Common/Makefiles/Android/src/com/visioglobe/VisioSample/Interfaces/VgMyInstructionUpdateListener.java

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */
package com.visioglobe.VisioSample.Interfaces;

public interface VgMyInstructionUpdateListener
{

    public void goToInstruction(int pInstructionIndex);
}

./Common/Makefiles/Android/src/com/visioglobe/VisioSample/Interfaces/VgMyLayerAndCameraHandler.java

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

package com.visioglobe.VisioSample.Interfaces;

import com.visioglobe.libVisioDevKit.VgIViewPoint;
import com.visioglobe.libVisioDevKit.VgPosition;

public interface VgMyLayerAndCameraHandler
{  
    public boolean isGlobalView();
    
    public void switchToGlobalView(boolean pIsAnimated);
    
    public void switchToDetailedView(boolean pIsAnimated);
    
    public String getFocusedLayerName();
    
    public void gotoLayer(String pLayerName, boolean pIsAnimated);
    
    public void gotoLayer(long pLayerIndex, boolean pIsAnimated);
    
    public void gotoViewpoint(VgIViewPoint pViewPoint, String pLayerName, boolean pIsAnimated);
    
    
    public void gotoLookAtPosition(VgPosition pPosition, String pLayerName, boolean pIsAnimated);    
    
    public void refreshParameters(long pWidth, long pHeight);

    public void release();

}

./Common/Makefiles/Android/src/com/visioglobe/VisioSample/Interfaces/VgMyLayerAndCameraListener.java

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */


package com.visioglobe.VisioSample.Interfaces;

public interface VgMyLayerAndCameraListener
{
    public void layerWillChangeFrom(VgMyLayerAndCameraHandler pSender, String pLayerFrom, String pLayerTo);
    
    public void layerChangedTo(VgMyLayerAndCameraHandler pSender, String pFloorFrom, String pFloorTo);
    
    
    public void viewWillChange(VgMyLayerAndCameraHandler pSender, boolean pDoesChangeFromGlobalToDetailed);

    
    
    public void viewDidChange(VgMyLayerAndCameraHandler pSender, boolean pDoesChangeFromGlobalToDetailed);
}

./Common/Makefiles/Android/src/com/visioglobe/VisioSample/Interfaces/VgMyNavigationCreator.java

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */



package com.visioglobe.VisioSample.Interfaces;

import com.visioglobe.libVisioDevKit.VgINavigationRequestParameters;


public interface VgMyNavigationCreator
{
    void createNavigation(VgINavigationRequestParameters pParameters);

    void release();
}

./Common/Makefiles/Android/src/com/visioglobe/VisioSample/Interfaces/VgMyNavigationPositionDisplay.java

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

package com.visioglobe.VisioSample.Interfaces;

import com.visioglobe.libVisioDevKit.VgINavigationConstRefPtr;
import com.visioglobe.libVisioDevKit.VgPosition;

public interface VgMyNavigationPositionDisplay extends VgMyDisplayable
{
    public void updateWithPosition(VgINavigationConstRefPtr pNavigation, VgPosition pPosition);
    
    public void clear();
    
    public void release();
}

./Common/Makefiles/Android/src/com/visioglobe/VisioSample/Interfaces/VgMyPoiConfigurationSetter.java

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */


package com.visioglobe.VisioSample.Interfaces;

import com.visioglobe.libVisioDevKit.VgIGeometryCallback;

public interface VgMyPoiConfigurationSetter
{

    public void setPoiCallback(String pIdentifier, VgIGeometryCallback pCallback);
}

./Common/Makefiles/Android/src/com/visioglobe/VisioSample/Interfaces/VgMyRouteCreator.java

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */


package com.visioglobe.VisioSample.Interfaces;

import com.visioglobe.libVisioDevKit.VgIRouteRequestParameters;
import com.visioglobe.libVisioDevKit.VgPosition;

public interface VgMyRouteCreator
{

    enum RoutePoint {
        eStart,
        eEnd
    };
    
    public boolean setRoutePoint(RoutePoint pPoint, String pPlaceID);
    
    
    public boolean setRoutePoint(RoutePoint pPoint, VgPosition pPosition);
    
    public void resetRoutePoint(RoutePoint pPoint);
    
    public boolean isRoutePointSet(RoutePoint pPoint);
    
    public void computeRoute();
    
    
    public VgIRouteRequestParameters editRoutingRequestParameters();
    
    public void resetRoutingRequestParameters();
    
    public void setAvoidStairs (boolean pDisabledFriendly);

    public void release();
    
}

./Common/Makefiles/Android/src/com/visioglobe/VisioSample/Interfaces/VgMyRouteDisplay.java

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */


package com.visioglobe.VisioSample.Interfaces;

import com.visioglobe.libVisioDevKit.VgIRouteConstRefPtr;

public interface VgMyRouteDisplay extends VgMyDisplayable
{
    public boolean createRouteObjects(VgIRouteConstRefPtr pRoute);
  
    public void clear();

    public void release();
}

./Common/Makefiles/Android/src/com/visioglobe/VisioSample/Utils/InstallActivity.java

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

package com.visioglobe.VisioSample.Utils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;

import com.visioglobe.VisioSample.R;
import com.visioglobe.VisioSample.VgMyBasicApplicationController;

/*
 * InstallActivity handles the extraction of the VisioDevKit dataset, located 
 * within the package, to the sdcard.    
 */
public class InstallActivity extends Activity
{   
    protected String mPreferencesFile = null;
    
    public ProgressDialog mProgressDialog;
    public static final int DIALOG_SPINNER_TYPE = 0;    
    protected static String mscEmbeddedMapsFolder = "EmbeddedMaps"; 
    protected String mExternalStoragePath;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        mPreferencesFile = getIntent().getExtras().getString(VgMyBasicApplicationController.mscPreferenceID);
    }

    @Override
    public void onResume()
    {
        super.onResume();

        if(isExternalStorageWritable())
        {
            String lMapBundleAssetPath = getMapBundlePathInAssetsDirectory();
            
            File lExternalStoragePath = getExternalFilesDir(null);
            mExternalStoragePath = lExternalStoragePath.toString() + "/" + mscEmbeddedMapsFolder;
            
            // If this directory already exists within the external storage.
            File lExternalEmbeddedMapStoragePath = new File(mExternalStoragePath);
            if(true == lExternalEmbeddedMapStoragePath.exists())
            {
                // Then delete it.
                deleteRecursive(lExternalEmbeddedMapStoragePath);
            }
            
            
            if(null != lMapBundleAssetPath)
            {
                if(lMapBundleAssetPath.endsWith(".zip"))
                {
                    // Perform unzip task
                    startUnzipMapBundle(lMapBundleAssetPath, mExternalStoragePath);
                }
                else
                {
                    // Perform copy task
                    startCopyMapBundle(lMapBundleAssetPath, mExternalStoragePath);
                }
            }
            else
            {
                fail();
            }
        }
        else
        {
            AlertDialog.Builder alertbox = new AlertDialog.Builder(this);
            alertbox.setTitle(R.string.app_name);
            alertbox.setIcon(android.R.drawable.ic_dialog_alert);
            alertbox.setMessage(R.string.externalStorageError);
            alertbox.setNeutralButton(
                getString(R.string.ok),
                new DialogInterface.OnClickListener()
                {
                    public void onClick(DialogInterface pDialogInterface, int pWhich)
                    {
                        fail();
                    }
                }
            );
            Dialog lDialog = alertbox.create();
            lDialog.show();
        }
    }
    
    
    @Override
    public void onPause()
    {
        super.onPause();
    }
    
    
    public boolean isExternalStorageAvailable()
    {
        boolean lIsExternalStorageAvailable = false;
        String state = Environment.getExternalStorageState();

        if (Environment.MEDIA_MOUNTED.equals(state) || 
                Environment.MEDIA_MOUNTED_READ_ONLY.equals(state) )
        {
            // We can read and write the media
            lIsExternalStorageAvailable = true;
        }
        return lIsExternalStorageAvailable;
    }

    public boolean isExternalStorageWritable()
    {
        boolean lIsExternalStorageWritable = false;
        String state = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equals(state)) 
        {
            lIsExternalStorageWritable = true;
        }
        return lIsExternalStorageWritable;
    }
    
    
    public String getMapBundlePathInAssetsDirectory()
    {
    
        InputStream lStream = null;
        String lMapBundlePathInAssetsDirectory = null;

        try {
            lStream = this.getAssets().open("DataManifest.xml");
        } 
        catch (IOException e1) 
        {
            Log.e("Vg", "Error: \"DataManifest.xml\" is missing from the \"assets\" directory");
            return lMapBundlePathInAssetsDirectory;
        }

        DocumentBuilderFactory lFactory = DocumentBuilderFactory.newInstance();
        Document lDom = null;
        DocumentBuilder lBuilder = null;

        try {
            lBuilder = lFactory.newDocumentBuilder();
            lDom = lBuilder.parse(lStream);
        } catch (Exception e) {
            Log.e("Vg", e.getMessage());
        }

        Element lRoot = lDom.getDocumentElement();
        String lRootNodeName = lRoot.getNodeName();
        // Support for single or multiple bundle.
        if (lRootNodeName.contentEquals("archive") || 
                lRootNodeName.contentEquals("archives")) 
        {
            String lMapBundleSource = lRoot.getAttribute("source");
            URI lArchUri = null;
            try
            {
                lArchUri = new URI(lMapBundleSource);
            }
            catch(URISyntaxException e)
            {
                Log.e("Vg", "Error: The source attribute within the \"DataManifest.xml\" contains an invalid path");
                return lMapBundlePathInAssetsDirectory;
            }

            String lArchProtocol = lArchUri.getScheme();

            if (lArchProtocol.contentEquals("asset"))
            {                   
                lMapBundlePathInAssetsDirectory = lArchUri.getPath().replaceAll("^/", "");

                return lMapBundlePathInAssetsDirectory;
            }
            else
            {
                Log.e("Vg", "Error: The \"asset\" protocol doesn't exist within the \"DataManifest.xml\" file");
                return lMapBundlePathInAssetsDirectory;
            }
        }

        return lMapBundlePathInAssetsDirectory;

    }
    
    
    private void startCopyMapBundle(String pMapBundleAssetPath, String pExternalStoragePath) 
    {       
        CopyAssetThread lMapBundleExtract= new CopyAssetThread(this, pExternalStoragePath + "/" + pMapBundleAssetPath);
        lMapBundleExtract.execute(pMapBundleAssetPath);
    }
    
    private void startUnzipMapBundle(String pMapBundleAssetPath, String pExternalStoragePath) 
    {
        UnzipAssetThread lMapBundleExtract= new UnzipAssetThread(this, pExternalStoragePath);
        lMapBundleExtract.execute(pMapBundleAssetPath);
    }
    
    public String getLocalConfigPathForMap(String pFromPath) 
    {
        final String sConfigName = "vg_config.xml";
        final String sConfigName2 = "vg_config.vge";

        File lDataElementFile = new File(pFromPath);

        File lConfigFile = findFile(lDataElementFile, sConfigName);

        if( (null != lConfigFile) && 
                (lConfigFile.exists()) )
        {
            return lConfigFile.getAbsolutePath();
        }

        lConfigFile = findFile(lDataElementFile, sConfigName2);

        if( (null != lConfigFile) && 
                (lConfigFile.exists()) )
        {
            return lConfigFile.getAbsolutePath();
        }       

        return "";
    }

    private File findFile(File pFile, String pToFind )
    {
        if( pFile.isFile() && 
                pFile.getName().contains( pToFind ) ) 
        {
            return pFile;
        } 
        else if( pFile.isDirectory() ) 
        {
            for( File child : pFile.listFiles() )
            {
                File found = findFile( child, pToFind );
                if( found != null ) 
                { 
                    return found;
                }
            }
        }
        return null;
    }
    
    void deleteRecursive(File fileOrDirectory) {
        if (fileOrDirectory.isDirectory())
            for (File child : fileOrDirectory.listFiles())
                deleteRecursive(child);

        fileOrDirectory.delete();
    }
    
    public void fail ()
    {
        setResult(RESULT_CANCELED);
        finish();
    }

    public void success ()
    {
        setResult(RESULT_OK);
        
        String lConfigPath = getLocalConfigPathForMap(mExternalStoragePath);
        
        SharedPreferences lPrefs = this.getSharedPreferences(mPreferencesFile, Context.MODE_PRIVATE);
        
        lPrefs.edit()
        .putString(VgMyBasicApplicationController.mscConfigFileDir, lConfigPath)
        .commit();
        
        finish();
    }
    
    
    @Override
    protected Dialog onCreateDialog(int id) {
        switch (id) 
        {
        case DIALOG_SPINNER_TYPE:
            mProgressDialog = new ProgressDialog(this);
            mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
            mProgressDialog.setTitle(R.string.titleExtractingMapBundle);
            mProgressDialog.setCancelable(false);
            mProgressDialog.show();
            return mProgressDialog; 
        default:
            return null;
        }
    }
}

./Common/Makefiles/Android/src/com/visioglobe/VisioSample/Utils/UnzipThread.java

./Common/Makefiles/Android/src/com/visioglobe/VisioSample/VgMyBasicApplicationController.java

/*
 * Copyright 2013, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 * 
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 * 
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 * 
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 * 
 * Contact information:  Visioglobe SAS, 
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */
package com.visioglobe.VisioSample;

import java.util.LinkedList;

import javax.microedition.khronos.opengles.GL10;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Build;
import android.widget.Toast;

import com.visioglobe.VisioSample.Interfaces.VgMyAnchoredDisplay;
import com.visioglobe.VisioSample.Interfaces.VgMyInstructionDisplay;
import com.visioglobe.VisioSample.Interfaces.VgMyInstructionUpdateListener;
import com.visioglobe.VisioSample.Interfaces.VgMyLayerAndCameraHandler;
import com.visioglobe.VisioSample.Interfaces.VgMyLayerAndCameraListener;
import com.visioglobe.VisioSample.Interfaces.VgMyLocationListener;
import com.visioglobe.VisioSample.Interfaces.VgMyLocationProvider;
import com.visioglobe.VisioSample.Interfaces.VgMyNavigationCreator;
import com.visioglobe.VisioSample.Interfaces.VgMyNavigationPositionDisplay;
import com.visioglobe.VisioSample.Interfaces.VgMyPoiConfigurationSetter;
import com.visioglobe.VisioSample.Interfaces.VgMyRouteCreator;
import com.visioglobe.VisioSample.Interfaces.VgMyRouteDisplay;
import com.visioglobe.libVisioDevKit.VgErrorCode;
import com.visioglobe.libVisioDevKit.VgI3DModule;
import com.visioglobe.libVisioDevKit.VgIApplication;
import com.visioglobe.libVisioDevKit.VgIDatabase;
import com.visioglobe.libVisioDevKit.VgIEngine;
import com.visioglobe.libVisioDevKit.VgIGeometryCallback;
import com.visioglobe.libVisioDevKit.VgIMapModule;
import com.visioglobe.libVisioDevKit.VgIModule;
import com.visioglobe.libVisioDevKit.VgIModuleManager;
import com.visioglobe.libVisioDevKit.VgINavigationCallback;
import com.visioglobe.libVisioDevKit.VgINavigationCallbackRefPtr;
import com.visioglobe.libVisioDevKit.VgINavigationConstRefPtr;
import com.visioglobe.libVisioDevKit.VgINavigationInstructionConstRefPtr;
import com.visioglobe.libVisioDevKit.VgINavigationListener;
import com.visioglobe.libVisioDevKit.VgINavigationListenerRefPtr;
import com.visioglobe.libVisioDevKit.VgINavigationModule;
import com.visioglobe.libVisioDevKit.VgINavigationRefPtr;
import com.visioglobe.libVisioDevKit.VgINavigationRequestParameters;
import com.visioglobe.libVisioDevKit.VgIRouteCallback;
import com.visioglobe.libVisioDevKit.VgIRouteCallbackRefPtr;
import com.visioglobe.libVisioDevKit.VgIRouteConstRefPtr;
import com.visioglobe.libVisioDevKit.VgIRouteRefPtr;
import com.visioglobe.libVisioDevKit.VgIRouteRequestParameters;
import com.visioglobe.libVisioDevKit.VgIRoutingModule;
import com.visioglobe.libVisioDevKit.VgIViewPoint;
import com.visioglobe.libVisioDevKit.VgModalityParameterType;
import com.visioglobe.libVisioDevKit.VgNavigationModalityParametersMap;
import com.visioglobe.libVisioDevKit.VgNavigationRequestStatus;
import com.visioglobe.libVisioDevKit.VgPosition;
import com.visioglobe.libVisioDevKit.VgPositionVector;
import com.visioglobe.libVisioDevKit.VgRouteRequestStatus;
import com.visioglobe.libVisioDevKit.libVisioDevKit;

public class VgMyBasicApplicationController 
implements
    VgMyLayerAndCameraListener, 
    VgMyLayerAndCameraHandler,
    VgMyRouteCreator,
    VgMyRouteDisplay,
    VgMyPoiConfigurationSetter,
    VgMyInstructionUpdateListener,
    VgMyAnchoredDisplay,
    VgMyLocationProvider,
    VgMyLocationListener,
    VgMySurfaceView.VgMySurfaceViewListener
{
    
    // ENCLOSED CLASSES ////////////////////////////////////////////////////////    

    class VgMyRouteCallback extends VgIRouteCallback
    {
        public VgMyRouteCallback() {
            super();
        }

        @SuppressLint("NewApi")
        @Override
        public void notifyRouteComputed(final VgRouteRequestStatus pStatus, final VgIRouteRefPtr pRoute) 
        {
            VgRouteRequestStatus mStatus = pStatus;
            mRoute = pRoute;

            if ( mStatus.swigValue() == VgRouteRequestStatus.eSuccess.swigValue() ) 
            {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) 
                {
                    // On Android 3.0 and higher, the options menu is considered to always be open 
                    // when menu items are presented in the action bar. 
                    // Must call invalidateOptionsMenu() to request that the system performs a menu update.
                    // Note: On Android 2.3.x and lower, the system calls onPrepareOptionsMenu() each time 
                    // the user opens the options menu (presses the Menu button).
                    mActivity.invalidateOptionsMenu();
                }
                
                if(true == createRouteObjects(new VgIRouteConstRefPtr(mRoute.get())))
                {
                    // notify VgMyRouteDisplay
                    mRouteDisplay.show();

                    // The mNavigationCallback object passed here will receive all notifications 
                    // regarding the navigation request.  
                    VgINavigationRequestParameters lRequestParams = new VgINavigationRequestParameters(0, mNavigationCallback, mRoute);
                    
                    
                    // Customize other attributes here.
                    VgNavigationModalityParametersMap lModalityParametersMap = new VgNavigationModalityParametersMap(); 
                    lModalityParametersMap.set(VgModalityParameterType.eStraightAngleThreshold, 180.0f);
                    lModalityParametersMap.set(VgModalityParameterType.eDistanceFromCouloirThreshold, 1000.0f);                 
                    lRequestParams.getMModalityParameters().set("shuttle", lModalityParametersMap);
                    
                    lRequestParams.setMMergeFloorChangeInstructions(false);
                    

                    // notify VgMyNavigationCreator
                    createNavigation(lRequestParams);
                }
            } 
            else if (mStatus.swigValue() == VgRouteRequestStatus.eError.swigValue()) 
            {
                mActivity.runOnUiThread(new Runnable() {
                    public void run() {
                        Toast.makeText(mActivity.getBaseContext(), mActivity.getResources().getString(R.string.messageErrorRouting), Toast.LENGTH_SHORT).show();
                    }
                });
            }

        }
    }
    
    class VgMyNavigationCallback extends VgINavigationCallback
    {
        public VgMyNavigationCallback()
        {
            super();
        }

        @Override
        public boolean notifyNavigationComputed(VgNavigationRequestStatus pStatus, VgINavigationRefPtr pNavigation) 
        {
            boolean lRequestNotifyNewInstruction = true;

            // Verify navigation was successfully computed
            if (pStatus.swigValue() == VgNavigationRequestStatus.eSuccess.swigValue()) 
            {
                // It is very important that we make a copy here, since
                // assignment in java would simply fetch the reference to
                // the VgINavigationRefPtr passed, which will be deleted
                // when we exit this method, since it lives in the C++
                // stack.
                // 
                // mNavigation = pNavigation; <=== BAD
                mNavigation = new VgINavigationRefPtr(pNavigation);
                
                // Once the navigation listener is added to the navigation object the navigation object
                // will be responsible of notifying the listener of navigation events.  
                // Please refer the VgINavigationListener class for what notifications there are. 
                mNavigation.addListener(mNavigationListener);

            } 
            // There was an error computing navigation
            else if ( pStatus.swigValue() == VgNavigationRequestStatus.eError.swigValue() ) 
            {
                mActivity.runOnUiThread(new Runnable() 
                {
                    public void run() 
                    { 
                        Toast.makeText(mActivity.getBaseContext(), mActivity.getResources().getString(R.string.messageErrorNavigation), Toast.LENGTH_SHORT).show();
                    }
                });
            }
            
            return lRequestNotifyNewInstruction;
        }
    }

    
    class VgMyNavigationListener extends VgINavigationListener
    {
        
        public VgMyNavigationListener()
        {
            super();
        }

        @Override
        public void notifyPositionUpdated(final VgINavigationConstRefPtr pNavigation, VgPosition pPosition, double pTime) 
        {
            VgPosition mPosition = new VgPosition(pPosition);

            // notify VgMyNavigationPositionDisplay interface
            updateWithPosition(pNavigation, mPosition);
        }

        @Override
        public void notifyNewInstruction(final VgINavigationConstRefPtr pNavigation, final long pIndex)
        {
            long mIndex = pIndex;

            // notify VgMyInstructionDisplays interface
            updateWithInstruction(pNavigation, mIndex);
            showInstructionDisplays();
        }
    }

    // STATIC FIELD ////////////////////////////////////////////////////////
    public static final String mscPreferenceID = "preferenceID";
    public static final String mscPreferencesFile = "preferenceFile";
    public static final String mscConfigFileDir = "vg_config_xml";
    
    // CONFIGURABLE FIELDS //////////////////////////////////////////////////////// 
    // IMPORTANT : Do not set the configurable members here directly.  Instead use the 
    // setter methods provided, for example setSecretCode().
    private String mLicenseUrl = "";
    private String mConfigurationFile = "";
    private static final long mscInvalidSecretCode = ~0;
    private long mSecretCode = mscInvalidSecretCode;

    // FIELDS POPULATED @ CONSTRUCTION ////////////////////////////////////////////////////////
    protected Activity mActivity;
    protected VgMySurfaceView mSurfaceView;
    public VgIRouteCallbackRefPtr mRouteCallback;
    public VgINavigationCallbackRefPtr mNavigationCallback;
    public VgINavigationListenerRefPtr mNavigationListener;
    
    // FIELDS POPULATED @ RESTORE ////////////////////////////////////////////////////////
    protected VgIApplication mVgApplication;
    protected VgIEngine mVgEngine;
    protected VgIDatabase mVgDatabase;
    protected VgIMapModule mMapModule;
    protected VgI3DModule m3DModule;
    protected VgIRoutingModule mRoutingModule;
    protected VgINavigationModule mNavigationModule;

    // BLOCKS FIELDS ////////////////////////////////////////////////////////
    // A linked list is used for interfaces where it's possible/desirable to 
    // have more than one object listener
    protected VgINavigationRefPtr mNavigation;
    // The current route (only one at a time)
    protected VgIRouteRefPtr mRoute;
    protected VgMyLayerAndCameraHandler mLayerAndCameraHandler;
    protected VgMyRouteCreator mRouteCreator;
    protected VgMyRouteDisplay mRouteDisplay;
    protected VgMyAnchoredDisplay mAnchoredDisplay;
    protected VgMyNavigationCreator mNavigationCreator;
    protected VgMyLocationProvider mLocationProvider;
    protected LinkedList<VgMyLayerAndCameraListener> mLayerAndCameraListeners = new LinkedList<VgMyLayerAndCameraListener>();
    protected LinkedList<VgMyNavigationPositionDisplay> mNavigationPositionDisplays = new LinkedList<VgMyNavigationPositionDisplay>();
    protected LinkedList<VgMyInstructionDisplay> mInstructionsDisplays = new LinkedList<VgMyInstructionDisplay>();
    
    /*
     * Constructor
     */
    public VgMyBasicApplicationController(Activity pActivity, VgMySurfaceView pSurfaceView)
    {
        mActivity = pActivity;
        mSurfaceView = pSurfaceView;
        // Set a listener on the surface view to be notified of surface view related events
        mSurfaceView.addSurfaceViewListener(this);
        
        mRouteCallback = new VgIRouteCallbackRefPtr(new VgMyRouteCallback());
        
        mNavigationCallback = new VgINavigationCallbackRefPtr(new VgMyNavigationCallback());
        
        mNavigationListener = new VgINavigationListenerRefPtr(new VgMyNavigationListener());
    }
        
    public boolean loadConfiguration(String pConfiguration, long pSecretKey, String pLicenseURL, long pDataset)
    {
        if(false == isVisioDevKitValid())
        {
            return false;
        }

        // Load configuration
        if(false == mVgDatabase.loadConfiguration(pConfiguration, pSecretKey, pLicenseURL))
        {
            return false;
        }
        
        if(false == mVgDatabase.selectDataset((int)pDataset))
        {
            return false;
        }
        
        return true;
    }

    public void reinitAppBlocks()
    {
        // VisioDevKit objects
        mVgDatabase.unloadConfiguration();
        mVgApplication = null;
        mVgEngine = null;
        mVgDatabase = null;
        mMapModule = null;
        m3DModule = null;
        mRoutingModule = null;
        mNavigationModule  = null;

        // Block objects
        release();
        mNavigation = null;
        mLayerAndCameraHandler = null;
        mRouteCreator = null;
        mRouteDisplay = null;
        mAnchoredDisplay = null;
        mNavigationCreator = null;
        mLocationProvider = null;
        mLayerAndCameraListeners.clear();
        mNavigationPositionDisplays.clear();
        mInstructionsDisplays.clear();
    }
    
    public void setLayerAndCameraHandler(VgMyLayerAndCameraHandler pHandler)
    {
        mLayerAndCameraHandler = pHandler;
    }

    public void setRouteCreator(VgMyRouteCreator pCreator)
    {
        mRouteCreator = pCreator;
    }
    
    // Multiple VgMyRouteDisplay could be used. See addNavigationDisplay for example.
    public void setRouteDisplay(VgMyRouteDisplay pDisplay)
    {
        mRouteDisplay = pDisplay;
    }

    public void setNavigationCreator(VgMyNavigationCreator pCreator)
    {
        mNavigationCreator = pCreator;
    }
    
    public void addLayerAndCameraListener(VgMyLayerAndCameraListener pListener)
    {
        mLayerAndCameraListeners.add(pListener);
    }
    
    public void addNavigationPositionDisplay(VgMyNavigationPositionDisplay pDisplay)
    {
        mNavigationPositionDisplays.add(pDisplay);
    }
    
    public void addInstructionDisplay(VgMyInstructionDisplay pDisplay)
    {
        mInstructionsDisplays.add(pDisplay);
    }
    
    public void setAnchoredDisplay(VgMyAnchoredDisplay pBubbleView)
    {
        mAnchoredDisplay = pBubbleView;
    }
    
    public void setLocationProvider(VgMyLocationProvider pLocationProvider)
    {
        mLocationProvider = pLocationProvider;
    }

    public boolean has3DModule()
    {
        return (null != m3DModule);
    }
    
    public boolean hasMapModule()
    {
        return (null != mMapModule);
    }
    
    public boolean hasRoutingModule()
    {
        return (null != mRoutingModule);
    }
    
    public boolean hasNavigationModule()
    {
        return (null != mNavigationModule);
    }

    public void setLicenseUrl(String pLicenseUrl)
    {
        mLicenseUrl = pLicenseUrl;
    }
    
    public void setSecretCode(long pSecretCode)
    {
        mSecretCode = pSecretCode;
    }
    
    public void setConfigurationFile(String pConfigurationFile)
    {
        mConfigurationFile = pConfigurationFile;
    }
    
    protected void retrieveVisioDevKit()
    {
        if(null != mSurfaceView)
        {
            mVgApplication = mSurfaceView.getApplication();
        }
        if(null != mVgApplication)
        {
            mVgEngine = mVgApplication.editEngine();
        }
        if(null != mVgEngine)
        {
            mVgDatabase = mVgEngine.editDatabase();
        }
    }
    
    protected void retrieveVisioDevKitModules()
    {
        if(true == isVisioDevKitValid())
        {
            // Set up the modules (the vg_license.xml determines whether they're enabled 
            VgIModuleManager lModuleManager = mVgApplication.editModuleManager();
            if (null != lModuleManager) 
            {
                VgIModule lMapModule = lModuleManager.queryModule("Map");
                if(null != lMapModule)
                {
                    mMapModule = libVisioDevKit.castToIMapModule(lMapModule);
                }

                VgIModule l3DModule = lModuleManager.queryModule("3D");
                if(null != l3DModule)
                {
                    m3DModule = libVisioDevKit.castToI3DModule(l3DModule);
                }

                VgIModule lRoutingModule = lModuleManager.queryModule("Routing");
                if(null != lRoutingModule)
                {
                    mRoutingModule = libVisioDevKit.castToIRoutingModule(lRoutingModule);
                }

                VgIModule lNavigationModule = lModuleManager.queryModule("Navigation");
                if(null != lNavigationModule)
                {
                    mNavigationModule = libVisioDevKit.castToINavigationModule(lNavigationModule);
                }   
            }
        }
    }
    
    public boolean isVisioDevKitValid()
    {
        if( (null == mSurfaceView) ||
            (null == mVgApplication) ||
            (null == mVgEngine) ||
            (null == mVgDatabase) )
        {
            return false;
        }

        return true;
    }
    
    
    /*
     * Calculate a view point given a single position.
     */
    protected VgIViewPoint getViewpointFromPosition(VgPosition pPos)
    {
        if(true == isVisioDevKitValid())
        {
            // Define the space around the position
            int lTop = 20;
            int lBottom = 20;
            int lLeft = 20; 
            int lRight = 20;

            VgPositionVector lVisiblePositions = new VgPositionVector();
            lVisiblePositions.add(pPos);
            // We use getViewpointFromPositions to take into account the fact that the pitch might not be -90.
            VgIViewPoint lViewPoint = mVgEngine.editCamera().getViewpointFromPositions(lVisiblePositions, lTop, lBottom, lLeft, lRight);
            return lViewPoint;
        }
        else
        {
            return null;
        }
    }
    
    

    
/************************************************************************************************************************
 * Below are the implemented interfaces 
 */

    /********************************************************
    * @implements VgMyInstructionUpdateListener::goToInstruction
    */
    public void goToInstruction(int pInstructionIndex)
    {
        if ((mNavigation != null) &&
                (mNavigation.isValid()) &&
                (pInstructionIndex < mNavigation.getNumInstructions() ) && 
                (pInstructionIndex >= 0) )
        {
            mNavigationListener.notifyNewInstruction(new VgINavigationConstRefPtr(mNavigation.get()), pInstructionIndex);

            VgINavigationInstructionConstRefPtr lInstruction = mNavigation.getInstruction(pInstructionIndex);
            VgPosition lInstructionPosition = lInstruction.getPosition();
            
            gotoLookAtPosition(lInstructionPosition, lInstruction.getLayer(), true);
        }
    }   


    public boolean setup() 
    {
        // Retrieve the basic VisioDevKit elements
        retrieveVisioDevKit();
        
        if(false == isVisioDevKitValid())
        {
            return true;
        }
        
        if(false == loadConfiguration(mConfigurationFile, mSecretCode, mLicenseUrl, 0))
        {
            VgErrorCode lErrorCode = mVgEngine.getLastError();
            String lErrorStr = mVgEngine.getErrorString(lErrorCode);
            
            final String lError = "loadConfiguration failed: " + lErrorStr;
            
            mActivity.runOnUiThread(new Runnable() 
            {
                public void run() 
                {
                    // Display dialog with error
                    AlertDialog.Builder alertbox = new AlertDialog.Builder(mActivity);
                    alertbox.setMessage(lError);
                    alertbox.setNeutralButton("Close", new DialogInterface.OnClickListener() 
                    {
                        public void onClick(DialogInterface arg0, int arg1) 
                        {}
                    });
                    alertbox.show();
                }
            });
            
            return false;
        }
        
        // Retrieve the VisioDevKit modules (they can only be retrieved after 
        // the configuration has been successfully performed.
        retrieveVisioDevKitModules();
        
        return true;
    }
    
    /********************************************************
     * @implements VgMySurfaceView.VgMySurfaceViewListener
     * 
     */
    public void onSurfaceChanged(GL10 gl, int pWidth, int pHeight)
    {}
    
    public void onSurfaceDestroyed()
    {}  
    
    /********************************************************
     * @implements VgMyLayerAndCameraListener 
     */
    
    public void layerWillChangeFrom(VgMyLayerAndCameraHandler pSender, String pFloorFrom, String pFloorTo)
    {
        for(VgMyLayerAndCameraListener lLayerUpdateListener : mLayerAndCameraListeners)
        {
            lLayerUpdateListener.layerWillChangeFrom(pSender, pFloorFrom, pFloorTo);
        }   
    }
    
    public void layerChangedTo(VgMyLayerAndCameraHandler pSender, String pFloorFrom, String pFloorTo)
    {
        for(VgMyLayerAndCameraListener lLayerUpdateListener : mLayerAndCameraListeners)
        {
            lLayerUpdateListener.layerChangedTo(pSender, pFloorFrom, pFloorTo);
        }
    }
    
    public void viewWillChange(VgMyLayerAndCameraHandler pSender, boolean pDoesChangeFromGlobalToDetailed)
    {
        for(VgMyLayerAndCameraListener lLayerUpdateListener : mLayerAndCameraListeners)
        {
            lLayerUpdateListener.viewWillChange(pSender, pDoesChangeFromGlobalToDetailed);
        }
    }

    public void viewDidChange(VgMyLayerAndCameraHandler pSender, boolean pDoesChangeFromGlobalToDetailed)
    {
        for(VgMyLayerAndCameraListener lLayerUpdateListener : mLayerAndCameraListeners)
        {
            lLayerUpdateListener.viewDidChange(pSender, pDoesChangeFromGlobalToDetailed);
        }
    }
    
    /********************************************************
     * @implements VgMyLayerAndCameraHandler 
     */
    public boolean isGlobalView()
    {
        if(null != mLayerAndCameraHandler) {
            return mLayerAndCameraHandler.isGlobalView();
        } else {
            return false;
        }
    }
    
    public void switchToGlobalView(boolean pIsAnimated)
    {
        if(null != mLayerAndCameraHandler) {
            mLayerAndCameraHandler.switchToGlobalView(pIsAnimated);
        }
    }
    
    public void switchToDetailedView(boolean pIsAnimated)
    {
        if(null != mLayerAndCameraHandler) {
            mLayerAndCameraHandler.switchToDetailedView(pIsAnimated);
        }
    }

    // keeps current mode.
    public void gotoLayer(String pLayerName, boolean pIsAnimated)
    {
        if(null != mLayerAndCameraHandler) 
        {
            mLayerAndCameraHandler.gotoLayer(pLayerName, pIsAnimated); 
        }
    }
    
    
    public void gotoLayer(long pLayerIndex, boolean pIsAnimated)
    {
        if(null != mLayerAndCameraHandler) 
        {
            mLayerAndCameraHandler.gotoLayer(pLayerIndex, pIsAnimated);
        }
    }
    
    public String getFocusedLayerName()
    {
        if(null != mLayerAndCameraHandler) {
            return mLayerAndCameraHandler.getFocusedLayerName();
        }
        return "";
    }
    
    
    public void gotoViewpoint(VgIViewPoint pViewPoint, String pLayerName, boolean pIsAnimated)
    {
        if(null != mLayerAndCameraHandler) {
            mLayerAndCameraHandler.gotoViewpoint(pViewPoint, pLayerName, pIsAnimated);
        }
    }
    
    public void gotoLookAtPosition(VgPosition pPosition, String pLayerName, boolean pIsAnimated) 
    {
        if(null != mLayerAndCameraHandler) {
            mLayerAndCameraHandler.gotoLookAtPosition(pPosition, pLayerName, pIsAnimated);
        }
    }
    
    public void refreshParameters(long pWidth, long pHeight)
    {
        if(null != mLayerAndCameraHandler) {
            mLayerAndCameraHandler.refreshParameters(pWidth, pHeight);
        }
    }
    
    /********************************************************
     * @implements VgMyRouteCreator 
     */
    
    // returns false, if no routing node.
    public boolean setRoutePoint(final RoutePoint pPoint, final String pPlaceID)
    {
        boolean lResult = false;

        if(null != mRouteCreator)
        {
            boolean lSuccess = mRouteCreator.setRoutePoint(pPoint, pPlaceID);

            if( lSuccess &&
                    isRoutePointSet(RoutePoint.eStart) && 
                    isRoutePointSet(RoutePoint.eEnd))
            {
                computeRoute();
                lResult = true;
            }
        }
        return lResult;
    }
    
    // returns false, if no routing node.
    public boolean setRoutePoint(final RoutePoint pPoint, final VgPosition pPosition)
    {
        boolean lResult = false;

        if(null != mRouteCreator)
        {
            boolean lSuccess = mRouteCreator.setRoutePoint(pPoint, pPosition);

            if( lSuccess &&
                    isRoutePointSet(RoutePoint.eStart) && 
                    isRoutePointSet(RoutePoint.eEnd))
            {
                computeRoute();
                lResult = true;
            }
        }
        return lResult;
    }

    public void resetRoutePoint(RoutePoint pPoint)
    {
        if(null != mRouteCreator) 
        {
            mRouteCreator.resetRoutePoint(pPoint);
        }
    }
    
    public boolean isRoutePointSet(RoutePoint pPoint)
    {
        if(null != mRouteCreator)
        {
            return mRouteCreator.isRoutePointSet(pPoint);
        }
        return false;
    }
    
    // works only if both end points are set
    public void computeRoute()
    {
        if(null != mRouteCreator)
        {
            mRouteCreator.computeRoute();
        }
    }
    
    public VgIRouteRequestParameters editRoutingRequestParameters()
    {
        if (null != mRouteCreator)
        {
            return mRouteCreator.editRoutingRequestParameters();
        }
        return null;
    }


    public void resetRoutingRequestParameters()
    {
        if (null != mRouteCreator)
        {
            mRouteCreator.resetRoutingRequestParameters();
        }
    }
    
    public void setAvoidStairs (boolean pDisabledFriendly)
    {
        if (null != mRouteCreator)
        {
            mRouteCreator.setAvoidStairs(pDisabledFriendly);
        }
    }
    
    /********************************************************
     * @implements VgMyRouteDisplay 
     */
    public boolean createRouteObjects(VgIRouteConstRefPtr pRoute)
    {
        if(null != mRouteDisplay)
        {
            return mRouteDisplay.createRouteObjects(pRoute);
        }
        else
        {
            return false;
        }
    }
    
    public void clearRouteDisplay()
    {
        if(null != mRouteDisplay)
        {
            mRouteDisplay.clear();
        }
        mRoute = null;
    }
    
    public boolean isVisibleRouteDisplay()
    {
        if(null != mRouteDisplay)
        {
            return mRouteDisplay.isVisible();
        }
        return false;
    }
    
    public void showRouteDisplay()
    {
        if(null != mRouteDisplay)
        {
            mRouteDisplay.show();
        }
    }
    
    public void hideRouteDisplay()
    {
        if(null != mRouteDisplay)
        {
            mRouteDisplay.hide();
        }
    }

    
    /********************************************************
     * @implements VgMyPoiConfigurationSetter
     * 
     */
    public void setPoiCallback(String pIdentifier, VgIGeometryCallback pCallback)
    {
        //Log.i("Vg", "setPoiCallback: -> implement if desired.");
    }
    
    
    /**********************************************************************************************************
     * @implements VgMyNavigationCreator
     */
    
    public void createNavigation(VgINavigationRequestParameters pParameters)
    {
        if(null != mNavigationCreator) {
            mNavigationCreator.createNavigation(pParameters);
        }
    }
    
    /**********************************************************************************************************
     * @implements VgMyNavigationPositionDisplay
     */ 
    
    public void updateWithPosition(VgINavigationConstRefPtr pNavigation, VgPosition pPosition)
    {
        for(VgMyNavigationPositionDisplay lNavPosDisplay : mNavigationPositionDisplays)
        {
            lNavPosDisplay.updateWithPosition(pNavigation, pPosition);
            lNavPosDisplay.show();
        }
    }
    
    public void clearNavigationPositionDisplays()
    {
        for(VgMyNavigationPositionDisplay lNavPosDisplay : mNavigationPositionDisplays)
        {
            lNavPosDisplay.clear();
        }
        mNavigation = null;
    }
    
    public void showNavigationPositionDisplays()
    {
        for(VgMyNavigationPositionDisplay lNavPosDisplay : mNavigationPositionDisplays)
        {
            if(false == lNavPosDisplay.isVisible())
            {
                lNavPosDisplay.show();
            }
        }
    }
    
    public void hideNavigationPositionDisplays()
    {
        for(VgMyNavigationPositionDisplay lNavPosDisplay : mNavigationPositionDisplays)
        {
            if(true == lNavPosDisplay.isVisible())
            {
                lNavPosDisplay.hide();
            }
        }
    }
    
    
    /**********************************************************************************************************
     * @implements VgMyAnchoredDisplay
     */ 
    
    public void setAnchorPosition(String pPlaceID, VgPosition pPosition)
    {
        if(null != mAnchoredDisplay)
        {
            mAnchoredDisplay.setAnchorPosition(pPlaceID, pPosition);
        }
    }
    
    public void showAnchoredDisplay()
    {
        if(null != mAnchoredDisplay)
        {
            mAnchoredDisplay.show();
        }   
    }
    
    public void hideAnchoredDisplay()
    {
        if(null != mAnchoredDisplay)
        {
            mAnchoredDisplay.hide();
        }
    }
    
    /**********************************************************************************************************
     * @implements VgMyNavigationDisplay
     */ 
    
    public void updateWithInstruction(VgINavigationConstRefPtr pNavigation, long pIndex)
    {
        for(VgMyInstructionDisplay lInstructionDisplay : mInstructionsDisplays)
        {
            lInstructionDisplay.updateWithInstruction(pNavigation, pIndex);
        }
    }
    
    public void showInstructionDisplays()
    {
        for(VgMyInstructionDisplay lInstructionDisplay : mInstructionsDisplays)
        {   
            if(false == lInstructionDisplay.isVisible())
            {
                lInstructionDisplay.show();
            }
        }
    }
    
    public void hideInstructionDisplays()
    {
        for(VgMyInstructionDisplay lInstructionDisplay : mInstructionsDisplays)
        {   
            if(true == lInstructionDisplay.isVisible())
            {
                lInstructionDisplay.hide();
            }
        }
    }
    
    public void clearInstructionDisplays()
    {
        for(VgMyInstructionDisplay lInstructionDisplay : mInstructionsDisplays)
        {
            lInstructionDisplay.clear();
        }
    }
    
    /**********************************************************************************************************
     * @implements VgMyDisplayable
     */     
    public void clear()
    {}
    
    /**********************************************************************************************************
     * @implements VgMyDisplayable
     */     
    public void show()
    {}

    public void hide()
    {}

    public boolean isVisible()
    {return false;}

    
    
    /**********************************************************************************************************
     * @implements VgMyLocationProvider
     */ 
    
    public void enable() 
    {
        if(null != mLocationProvider)
        {
            mLocationProvider.enable();
        }
    }

    public void disable() 
    {   
        if(null != mLocationProvider)
        {
            mLocationProvider.disable();
        }
    }
    
    public boolean isEnabled() 
    {
        boolean lIsEnabled = false;
        if(null != mLocationProvider)
        {
            lIsEnabled = mLocationProvider.isEnabled();
        }
        return lIsEnabled;
    }

    public void setListener(VgMyLocationListener pListener) 
    {
        if(null != mLocationProvider)
        {
            mLocationProvider.setListener(pListener);
        }
    }
    
    /**********************************************************************************************************
     * @implements VgMyLocationListener
     */ 
    public void updatePosition(VgPosition pPosition)
    {
        if(null != mNavigation)
        {
            mNavigation.updateCurrentPosition(pPosition, 0);
        }
        else if (null != mNavigationListener)
        {
            mNavigationListener.notifyPositionUpdated(VgINavigationConstRefPtr.getNull(), pPosition, 0.0);
        }
    }

    @Override
    public void release()
    {
        disable(); // Disable positioning
        hideAnchoredDisplay();
        hideInstructionDisplays();
        hideNavigationPositionDisplays();
        hideRouteDisplay();
        clearRouteDisplay();
        clearInstructionDisplays();
        clearNavigationPositionDisplays();
        
        

        if(null != mRouteCreator)
        {
            mRouteCreator.release();
            mRouteCreator = null;
        }
        if(null != mRouteDisplay)
        {
            mRouteDisplay.release();
            mRouteDisplay = null;
        }
        if(null != mAnchoredDisplay)
        {
            mAnchoredDisplay.release();
            mAnchoredDisplay = null;
        }
        if(null != mNavigationCreator)
        {
            mNavigationCreator.release();
            mNavigationCreator = null;
        }
        if(null != mLocationProvider)
        {
            mLocationProvider.release();
            mLocationProvider = null;
        }
        if(null != mLayerAndCameraHandler)
        {
            mLayerAndCameraHandler.release();
            mLayerAndCameraHandler = null;
        }
        
        if (mInstructionsDisplays != null)
        {
            for (VgMyInstructionDisplay lInstDisp : mInstructionsDisplays)
            {
                lInstDisp.release();
            }
            mInstructionsDisplays.clear();
        }
        
        if (mNavigationPositionDisplays != null)
        {
            for (VgMyNavigationPositionDisplay lNavPosDisp : mNavigationPositionDisplays)
            {
                //lNavPosDisp.release();
            }
            mNavigationPositionDisplays.clear();
        }
        
        if (mLayerAndCameraListeners != null)
        {
            mLayerAndCameraListeners.clear();
        }
        
        if (mNavigation != null)
        {
            if(mNavigation.isValid())
            {
                mNavigation.removeListener(mNavigationListener);
            }
            mNavigation = null;
        }
        
        mNavigationListener = null;
        mNavigationCallback = null;
        
        mRoute = null;
        mRouteCallback = null;
        
        // VisioDevKit objects
        mVgDatabase.unloadConfiguration();
        mVgApplication = null;
        mVgEngine = null;
        mVgDatabase = null;
        mMapModule = null;
        m3DModule = null;
        mRoutingModule = null;
        mNavigationModule  = null;
                
        mActivity = null;
    }
}

./Common/Makefiles/Android/src/com/visioglobe/VisioSample/VgMyGeometryManager.java

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */
package com.visioglobe.VisioSample;

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;

import com.visioglobe.libVisioDevKit.VgIGeometryCallbackRefPtr;
import com.visioglobe.libVisioDevKit.VgInstanceFactory;
import com.visioglobe.libVisioDevKit.VgLayerRefPtr;
import com.visioglobe.libVisioDevKit.VgLineDescriptorRefPtr;
import com.visioglobe.libVisioDevKit.VgLineRefPtr;
import com.visioglobe.libVisioDevKit.VgLinkDescriptorRefPtr;
import com.visioglobe.libVisioDevKit.VgLinkRefPtr;
import com.visioglobe.libVisioDevKit.VgPointDescriptorRefPtr;
import com.visioglobe.libVisioDevKit.VgPointRefPtr;

public class VgMyGeometryManager
{

    public class LinkObject
    {
        VgLinkRefPtr mLink;
    }

    public class LineObject
    {
        VgLineRefPtr mLine;
        String mLayerName;
    }
        
    public class PointObject
    {
        public VgPointRefPtr mPoint;
        public VgIGeometryCallbackRefPtr mCallback;
        
        // Any changes to the layer must be called via the the method 
        // to ensure that corresponding members are updated.
        private String mLayerName;
        
        public void setLayerName(String pLayerName)
        {
            if( (null != mPoint) &&
                (false == mLayerName.contentEquals(pLayerName)) )
            {
                VgLayerRefPtr lLayer = mSurfaceView.getApplication().editEngine().editLayerManager().editLayer(pLayerName);
                if(null != lLayer)
                {
                    mLayerName = pLayerName;
                    mPoint.setLayer(lLayer);
                }
            }
        }
        
    }
    
    /*
     * The below are hash maps, where the key is a "context" is associated with a list of objects. 
     */
    private HashMap <String, LinkedList<LineObject> > mLineObjectMap = new HashMap <String, LinkedList<LineObject> > ();
    private HashMap <String, LinkedList<PointObject> > mPointObjectMap = new HashMap <String, LinkedList<PointObject> > ();
    private HashMap <String, LinkedList<LinkObject> > mLinkObjectMap = new HashMap <String, LinkedList<LinkObject> > ();
    
    // FIELDS //////////////////////////////////////////////////////////////////
    private VgMySurfaceView mSurfaceView;

    public VgMyGeometryManager (VgMySurfaceView pSurfaceView)
    {
        mSurfaceView = pSurfaceView;
    }
    
    
    public void addObjects()
    {
        addObjects(null);
    }
    
    
    public void addObjects(String pContext)
    {

        for(HashMap.Entry<String, LinkedList<LineObject> > lEntry : mLineObjectMap.entrySet() )
        {
            String lContext= lEntry.getKey();

            if( (null == pContext) ||
                    (true == lContext.contentEquals(pContext)))

            {
                LinkedList< LineObject > lLineObjects = lEntry.getValue();
                for(Iterator< LineObject > lIterator = lLineObjects.iterator(); lIterator.hasNext();) 
                {
                    LineObject lLineObject = lIterator.next();
                    VgLayerRefPtr lLayer = mSurfaceView.getApplication().editEngine().editLayerManager().editLayer(lLineObject.mLayerName);
                    lLineObject.mLine.setLayer(lLayer);
                }
            }
        }
        
        
        for(HashMap.Entry<String, LinkedList<LinkObject> > lEntry : mLinkObjectMap.entrySet() )
        {
            String lContext= lEntry.getKey();

            if( (null == pContext) ||
                    (true == lContext.contentEquals(pContext)))

            {
                LinkedList< LinkObject > lLinkObjects = lEntry.getValue();
                for(Iterator< LinkObject > lIterator = lLinkObjects.iterator(); lIterator.hasNext();) 
                {
                    LinkObject lLinkObject = lIterator.next();
                    lLinkObject.mLink.setVisible(true);
                }
            }
        }


        for(HashMap.Entry<String, LinkedList<PointObject> > lEntry : mPointObjectMap.entrySet() )
        {
            String lContext= lEntry.getKey();

            if( (null == pContext) ||
                (true == lContext.contentEquals(pContext)))

            {
                LinkedList< PointObject > lPointObjects = lEntry.getValue();

                for(Iterator< PointObject > lIterator = lPointObjects.iterator(); lIterator.hasNext();) {
                    PointObject lPointObject = lIterator.next();

                    VgLayerRefPtr lLayer = mSurfaceView.getApplication().editEngine().editLayerManager().editLayer(lPointObject.mLayerName);
                    lPointObject.mPoint.setLayer(lLayer);

                    if(lPointObject.mCallback != null)
                    {
                        lPointObject.mPoint.addListener(lPointObject.mCallback);
                    }
                }
            }
        }
    }

    public VgLineRefPtr createLineObject(String pContext, String pLayerName, VgLineDescriptorRefPtr lLineDescr)
    {
        LineObject lObject = new LineObject();
        
        VgInstanceFactory lInstanceFactory = mSurfaceView.getApplication().editEngine().editInstanceFactory();
        
        lObject.mLine = lInstanceFactory.instantiate(lLineDescr);
        
        if(lObject.mLine.isValid())
        {
            VgLayerRefPtr lLayer = mSurfaceView.getApplication().editEngine().editLayerManager().editLayer(pLayerName);
            lObject.mLine.setLayer(lLayer);

            lObject.mLayerName = pLayerName;

            LinkedList< LineObject > lLineObjectList = mLineObjectMap.get(pContext);
            if (lLineObjectList == null)
            {
                lLineObjectList = new LinkedList< LineObject >();

            }
            lLineObjectList.add(lObject);
            mLineObjectMap.put(pContext, lLineObjectList);
        }
        return lObject.mLine;
    }
    
    public PointObject createPointObject(String pContext, String pLayerName, VgPointDescriptorRefPtr lPointDesc, VgIGeometryCallbackRefPtr pCallback)
    {
        PointObject lObject = new PointObject();
        VgInstanceFactory lInstanceFactory = mSurfaceView.getApplication().editEngine().editInstanceFactory();
                
        lObject.mPoint = lInstanceFactory.instantiate(lPointDesc);
        if( (null == lObject.mPoint) || 
                (false == lObject.mPoint.isValid()) )
        {
            // A problem occurred during the creation of the VgPoint object
            return null;
        }
        lObject.mPoint.setLayer(VgLayerRefPtr.getNull());
        lObject.mLayerName = pLayerName;
        lObject.mCallback = pCallback;
        
        if (pCallback != null)
        {
            lObject.mPoint.addListener(pCallback);
        }
        
        LinkedList< PointObject > lPointObjectList = mPointObjectMap.get(pContext);
        if (lPointObjectList == null)
        {
            lPointObjectList = new LinkedList< PointObject >();
        }
        lPointObjectList.add(lObject);
        mPointObjectMap.put(pContext, lPointObjectList);
        return lObject;
    }
    
    public VgLinkRefPtr createLinkObject(String pContext, VgLinkDescriptorRefPtr pLinkDescr)
    {
        LinkObject lObject = new LinkObject();
        VgInstanceFactory lInstanceFactory = mSurfaceView.getApplication().editEngine().editInstanceFactory();
        
        lObject.mLink = lInstanceFactory.instantiate(pLinkDescr);
        // Set not visible by default
        lObject.mLink.setVisible(false);

        LinkedList< LinkObject > lLinkObjectList = mLinkObjectMap.get(pContext);
        if (lLinkObjectList == null)
        {
            lLinkObjectList = new LinkedList< LinkObject >();
        }
        lLinkObjectList.add(lObject);
        mLinkObjectMap.put(pContext, lLinkObjectList);
        return lObject.mLink;
    }

    public void removeObjects (String pContext)
    {       
        LinkedList< LineObject > lLineObjects = mLineObjectMap.get(pContext);
        if(lLineObjects != null)
        {
            for(Iterator< LineObject > lIterator = lLineObjects.iterator(); lIterator.hasNext();) 
            {
                LineObject lLineObject = lIterator.next();
                lLineObject.mLine.setLayer(VgLayerRefPtr.getNull());
            }
        }
        
        LinkedList< LinkObject > lLinkObjects = mLinkObjectMap.get(pContext);
        if(lLinkObjects != null)
        {
            for(Iterator< LinkObject > lIterator = lLinkObjects.iterator(); lIterator.hasNext();) 
            {
                LinkObject lLinkObject = lIterator.next();
                lLinkObject.mLink.setVisible(false);
            }
        }

        LinkedList<PointObject> lPointObjects = mPointObjectMap.get(pContext);
        if(lPointObjects != null)
        {
            for(Iterator< PointObject > lIterator = lPointObjects.iterator(); lIterator.hasNext();) 
            {
                PointObject lPointObject = lIterator.next();
                lPointObject.mPoint.setLayer(VgLayerRefPtr.getNull());

                if(lPointObject.mCallback != null)
                {
                    lPointObject.mPoint.removeListener(lPointObject.mCallback); 
                }
            }
        }
    }
        
    public void removeObjects()
    {
        for (HashMap.Entry< String, LinkedList< LineObject > > lEntry : mLineObjectMap.entrySet()) 
        {
            LinkedList<LineObject> lLineObjects = lEntry.getValue();
            for(Iterator< LineObject > lIterator = lLineObjects.iterator(); lIterator.hasNext();) 
            {
                LineObject lLineObject = lIterator.next();
                lLineObject.mLine.setLayer(VgLayerRefPtr.getNull());
            }
        }
        
        for (HashMap.Entry< String, LinkedList< LinkObject > > lEntry : mLinkObjectMap.entrySet()) 
        {
            LinkedList<LinkObject> lLinkObjects = lEntry.getValue();
            for(Iterator< LinkObject > lIterator = lLinkObjects.iterator(); lIterator.hasNext();) 
            {
                LinkObject lLinkObject = lIterator.next();
                lLinkObject.mLink.setVisible(false);
            }
        }

        for (HashMap.Entry< String, LinkedList< PointObject > > lEntry : mPointObjectMap.entrySet()) 
        {
            LinkedList<PointObject> lPointObjects = lEntry.getValue();
            for(Iterator< PointObject > lIterator = lPointObjects.iterator(); lIterator.hasNext();) {
                PointObject lPointObject = lIterator.next();
                lPointObject.mPoint.setLayer(VgLayerRefPtr.getNull());

                if(lPointObject.mCallback != null)
                {
                    lPointObject.mPoint.removeListener(lPointObject.mCallback);
                }
            }
        }
    }

    public void deleteObjects (String pContext)
    {
        mLineObjectMap.remove(pContext);
        mLinkObjectMap.remove(pContext);
        mPointObjectMap.remove(pContext);
    }
    
    public void release()
    {
        mSurfaceView = null;
    }
}

./Common/Makefiles/Android/src/com/visioglobe/VisioSample/VgMySurfaceView.java

/*
 * Copyright 2013, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 * 
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 * 
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 * 
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 * 
 * Contact information:  Visioglobe SAS, 
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */
package com.visioglobe.VisioSample;

import java.util.LinkedList;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.util.AttributeSet;
import android.view.SurfaceHolder;

import com.visioglobe.libVisioDevKit.VgIApplication;
import com.visioglobe.libVisioDevKit.VgSurfaceView;


public final class VgMySurfaceView extends VgSurfaceView 
{
    static {
        System.loadLibrary("VisioDevKit");
    }


    public interface VgMySurfaceViewListener
    {    
        public void onSurfaceChanged(GL10 gl, int pWidth, int pHeight);

        public void onSurfaceDestroyed();

    };

    protected LinkedList<VgMySurfaceViewListener> mSurfaceViewListeners = new LinkedList<VgMySurfaceViewListener>();


    public VgMySurfaceView(Context pContext, AttributeSet pAttributeSet) 
    {
        super(pContext, pAttributeSet);
    }

    public VgMySurfaceView(Context pContext) 
    {
        super(pContext);
    }

    @Override
    public void onSurfaceCreated(GL10 pGL, EGLConfig pGLConfig) {
        super.onSurfaceCreated(pGL, pGLConfig);

        VgIApplication lVgApplication = getApplication();
        if (lVgApplication != null) 
        {
            lVgApplication.editEngine().resetGraphicResources(true);
        }
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int pWidth, int pHeight)
    {
        super.onSurfaceChanged(gl, pWidth, pHeight);

        for(VgMySurfaceViewListener lListener : mSurfaceViewListeners)
        {
            lListener.onSurfaceChanged(gl, pWidth, pHeight);
        }
    }

    public void addSurfaceViewListener(VgMySurfaceViewListener pSurfaceViewListener)
    {
        mSurfaceViewListeners.add(pSurfaceViewListener);
    }

    public void clearSurfaceViewListeners()
    {
        mSurfaceViewListeners.clear();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder pHolder)
    {
        for(VgMySurfaceViewListener lListener : mSurfaceViewListeners)
        {
            lListener.onSurfaceDestroyed();
        }
        clearSurfaceViewListeners();
        super.surfaceDestroyed(pHolder);
        pauseRendering();
    }

}

./Common/Makefiles/Android/src/com/visioglobe/VisioSample/VgMyTextureLoader.java

/*
 * Copyright 2013, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 * 
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 * 
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 * 
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 * 
 * Contact information:  Visioglobe SAS, 
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */
package com.visioglobe.VisioSample;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;

import android.app.Activity;
import android.content.res.AssetFileDescriptor;

import com.visioglobe.libVisioDevKit.VgBinaryBuffer;
import com.visioglobe.libVisioDevKit.VgBinaryBufferConstRefPtr;
import com.visioglobe.libVisioDevKit.VgIEngine;
import com.visioglobe.libVisioDevKit.VgITextureManager;
import com.visioglobe.libVisioDevKit.VgITextureRefPtr;
import com.visioglobe.libVisioDevKit.VgIconMarkerDescriptor;
import com.visioglobe.libVisioDevKit.VgIconMarkerDescriptorRefPtr;
import com.visioglobe.libVisioDevKit.VgMarkerDescriptorRefPtr;

public class VgMyTextureLoader
{   
    protected class TextureObject
    {
        boolean mTriedToLoad;
        int mResourceId;
        VgITextureRefPtr mTextureBuffer;
        
        public TextureObject(int pResourceId) 
        {
            mResourceId = pResourceId;
            mTriedToLoad = false;
            mTextureBuffer = null;
        }
    };

    protected class MarkerObject
    {
        boolean mTriedToLoad;
        String mImageName;
        VgIconMarkerDescriptorRefPtr mMarkerDesc;
        
        public MarkerObject(String pImageName)
        {
            mImageName = pImageName;
            mTriedToLoad = false;
        }
    };
    
    private HashMap<String, TextureObject> mTextureCache = new HashMap<String, TextureObject>();
    private HashMap<String, MarkerObject> mMarkerCache = new HashMap<String, MarkerObject>();

    
    private Activity mActivity;
    private VgMySurfaceView mSurfaceView;
    
    public VgMyTextureLoader(Activity pActivity, VgMySurfaceView pSurfaceView)
    {
        mActivity = pActivity;
        mSurfaceView = pSurfaceView;
    }
    
    /*
     * Sets the image to be used once a route has been computed
     * The image will be loaded the first time needed.
     * Use absolute paths if the application changes directory.
     */
    public void setImage (String pImageName, int pResourceId)
    {
        TextureObject lTexture = new TextureObject(pResourceId);
        mTextureCache.put(pImageName, lTexture);
    }
    
    /*
     * @returns true if the image has been set, otherwise false.
     */
    public boolean isImageSet(String pImageName)
    {
        if(null == mTextureCache.get(pImageName))
        {
            return false;
        }
        else
        {
            return true;
        }
    }

    /*
     * Unloads an image
     */
    public void resetImage (String pImageName)
    {
        mTextureCache.remove(pImageName);
    }
    
    
    /*
     * Sets the markers to be used once a route has been computed
     */
    public void setMarker (String pMarkerName, String pImageName)
    {
        MarkerObject lMarker = new MarkerObject(pImageName); 
        mMarkerCache.put(pMarkerName, lMarker);
    }
    
    /*
     * @returns true if the image has been set, otherwise false.
     */
    public boolean isMarkerSet(String pMarkerName)
    {
        if(null == mMarkerCache.get(pMarkerName))
        {
            return false;
        }
        else
        {
            return true;
        }
    }
    
    /*
     * Unloads a marker
     */
    public void resetMarker(String pMarkerName)
    {
        mMarkerCache.remove(pMarkerName);
    }

    
    /*
     * Returns a texture buffer.  If it has not been loaded, it loads it.
     * 
     * IMPORTANT: This method must always be called within the GL Thread
     */
    public VgITextureRefPtr getTextureBuffer(String pImageName)
    {
        TextureObject lTextureBuffer = mTextureCache.get(pImageName);
        
        if(lTextureBuffer == null)
        {
            return null;
        }
        else if (lTextureBuffer.mTriedToLoad == false)
        {
            lTextureBuffer.mTriedToLoad = true;

            VgIEngine lEngine = mSurfaceView.getApplication().editEngine();
            if ( null == lEngine )
            {
                return null;
            }
        
            VgITextureManager lTextureManager = lEngine.editTextureManager();
            if( null == lTextureManager )
            {
                return null;
            }
            lTextureBuffer.mTextureBuffer = createTextureFromResource(lTextureBuffer.mResourceId);
        }
        
        return lTextureBuffer.mTextureBuffer;
    }
    
    
    /*
     * Gets an icon marker descriptor with a default scale of 10.0 and
     * an image determined by the parameter pType.
     * 
     * IMPORTANT: This method must always be called within the GL Thread
     */
    public VgMarkerDescriptorRefPtr getMarker(String pMarkerName)
    {
        MarkerObject lMarkerDesc = mMarkerCache.get(pMarkerName);
        
        if(lMarkerDesc == null)
        {
            return null;
        }
        else if(false == lMarkerDesc.mTriedToLoad)
        {
            lMarkerDesc.mTriedToLoad = true;
            lMarkerDesc.mMarkerDesc = VgIconMarkerDescriptor.create(); 
            lMarkerDesc.mMarkerDesc.setMScale(20.f);
            lMarkerDesc.mMarkerDesc.setMIcon( getTextureBuffer(lMarkerDesc.mImageName));
        }
        return new VgMarkerDescriptorRefPtr(lMarkerDesc.mMarkerDesc.get());
    }
    
    
    protected VgITextureRefPtr createTextureFromResource(int pResourceId) 
    {
        VgBinaryBufferConstRefPtr lImageBuffer = new VgBinaryBufferConstRefPtr();
        byte[] lData = null;
        InputStream lImageStream = mActivity.getResources().openRawResource(pResourceId);
        // This is where we need the resource to be an uncompressed resource.
        AssetFileDescriptor lImageDesc = mActivity.getResources().openRawResourceFd(pResourceId);
        try {
            lData = new byte[(int) lImageDesc.getLength()];
            DataInputStream lDataIS = new DataInputStream(lImageStream);
            lDataIS.readFully(lData);
            lImageBuffer.set(new VgBinaryBuffer(lData, false));
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (lImageBuffer.isValid()) 
        {
            return mSurfaceView.getApplication().editEngine().editTextureManager().createTexture(lImageBuffer);
        } 
        else 
        {
            return null;
        }
    }
    
    public void release()
    {
        mActivity = null;
        mSurfaceView = null;
        mTextureCache.clear();
        mTextureCache = null;
        mMarkerCache.clear();
        mMarkerCache = null;
    }
}

./Common/Makefiles/Android/src/com/visioglobe/VisioSample/Blocks/VgMySimulatedLocationProvider.java

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */


package com.visioglobe.VisioSample.Blocks;

import java.util.Timer;
import java.util.TimerTask;

import android.app.Activity;

import com.visioglobe.VisioSample.VgMySurfaceView;
import com.visioglobe.VisioSample.Interfaces.VgMyLayerAndCameraHandler;
import com.visioglobe.VisioSample.Interfaces.VgMyLocationListener;
import com.visioglobe.VisioSample.Interfaces.VgMyLocationProvider;
import com.visioglobe.libVisioDevKit.VgICamera;
import com.visioglobe.libVisioDevKit.VgIMapModule;
import com.visioglobe.libVisioDevKit.VgIModule;
import com.visioglobe.libVisioDevKit.VgIModuleManager;
import com.visioglobe.libVisioDevKit.VgPosition;
import com.visioglobe.libVisioDevKit.VgPositionToolbox;
import com.visioglobe.libVisioDevKit.VgSRSConstRefPtr;
import com.visioglobe.libVisioDevKit.libVisioDevKit;

public class VgMySimulatedLocationProvider implements VgMyLocationProvider 
{
    // BLOCKS FIELDS ////////////////////////////////////////////////////////
    // A timer user to update the simulated position.
    protected Timer mSimulateTimer;

    protected VgMyLocationListener mLocationListener;
    protected VgMySurfaceView mSurfaceView;
    protected Activity mActivity;
    protected VgMyLayerAndCameraHandler mLayerAndCameraHandler;
    
    
    public VgMySimulatedLocationProvider(Activity pActivity, VgMySurfaceView pSurfaceView, VgMyLayerAndCameraHandler pLayerAndCameraHandler)
    {
        mActivity = pActivity;
        mSurfaceView = pSurfaceView;
        mLayerAndCameraHandler = pLayerAndCameraHandler;
        mLocationListener = null;
    }   
    
    /********************************************************
     * @implements Position Provider
     */ 
    
    public void simulatePosition()
    {
        // The simulatePosition uses the VgICamera within VisioDevKit to create a simulated
        // location.  So it's run within the GL Thread.
        //
        // IMPORTANT: If you use your own location provider block, don't forget that when you  
        // call the VgMyLocationListener.updatePosition() interface method, it should be called from 
        // within a GL thread.
        mSurfaceView.queueEvent(new Runnable()
        {
            public void run()
            {
                if ((false == mLayerAndCameraHandler.isGlobalView()) )
                {
                    VgICamera lCamera = mSurfaceView.getApplication().editEngine().editCamera();

                    VgPosition lCameraPosition = lCamera.getPosition();
                    double lPitch = lCamera.getPitch();
                    double lHeading = lCamera.getHeading();

                    double lDistanceToGround = lCameraPosition.getMZOrAltitude() / Math.abs(Math.sin(lPitch * Math.PI / 180.0));

                    VgPositionToolbox lPositionToolbox = mSurfaceView.getApplication().editEngine().getPositionToolbox();

                    VgPosition lGroundPositionOnCenterScreen = lPositionToolbox.offsetPosition(lCameraPosition, lHeading, lPitch, lDistanceToGround);
                    
                    // lCamera will probably be in a metric SRS.
                    // Convert position to Lat/Long to make it easier to debug, the next line is not mandatory.
                    lPositionToolbox.convert(lGroundPositionOnCenterScreen, VgSRSConstRefPtr.getNull());

                    String lLayer = mLayerAndCameraHandler.getFocusedLayerName();

                    // Computes the floor height of the focused layer
                    double lFloorHeight = 0.0;

                    VgIModuleManager lModuleManager = mSurfaceView.getApplication().editModuleManager();
                    if (null != lModuleManager) 
                    {
                        VgIModule lModule = lModuleManager.queryModule("Map");
                        if(null != lModule)
                        {
                            VgIMapModule lMapModule = libVisioDevKit.castToIMapModule(lModule);
                            if(null != lMapModule)
                            {
                                float[] lHeightMax = new float[1];
                                float[] lHeightMin = new float[1];
                                if ( lMapModule.getHeightRangeForLayer(lLayer, lHeightMax, lHeightMin))
                                {
                                    lFloorHeight = ((lHeightMax[0] + lHeightMin[0]) / 2);
                                }
                            }
                        }
                    }

                    // IMPORTANT: The floor height here is used to determine the layer 
                    // associated with a position.
                    lGroundPositionOnCenterScreen.setMZOrAltitude(lFloorHeight);

                    if(null != mLocationListener)
                    {
                        mLocationListener.updatePosition(lGroundPositionOnCenterScreen);
                    }
                }
            }
        });
    }
    
    public boolean isSimulatePositionEnabled()
    {
        if(null != mSimulateTimer)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    
    public void startSimulatePosition()
    {
        mSimulateTimer = new Timer();
        mSimulateTimer.schedule(new TimerTask() 
        {           
            @Override
            public void run() 
            {
                // The timer runs on the timer thread.  Need to run our simulatePostion method
                // back on the UI thread.
                simulatePosition();
            }
            
        }, 0, 2000);
    }

    public void stopSimulatePosition()
    {
        if(null != mSimulateTimer)
        {
            mSimulateTimer.cancel();
            mSimulateTimer.purge(); // Purge any cancel tasks still in the queue.
            mSimulateTimer = null;
        }
    }
    
    
    /**********************************************************************************************************
     * @implements VgMyLocationProvider
     */ 
    
    public void enable() 
    {
        if(false == isSimulatePositionEnabled())
        {
            startSimulatePosition();
        }
    }
    
    public boolean isEnabled()
    {
        return isSimulatePositionEnabled();
    }

    public void disable() 
    {   
        if(true == isSimulatePositionEnabled())
        {
            stopSimulatePosition();
        }
    }

    public void setListener(VgMyLocationListener pListener) 
    {
        mLocationListener = pListener;
    }

    @Override
    public void release()
    {
        mSimulateTimer = null;
        mLocationListener = null;
        mActivity = null;
        mLayerAndCameraHandler = null;
        
    }
}

./Common/Makefiles/Android/src/com/visioglobe/VisioSample/Interfaces/VgMyLocationListener.java

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

package com.visioglobe.VisioSample.Interfaces;

import com.visioglobe.libVisioDevKit.VgPosition;

public interface VgMyLocationListener 
{
    public void updatePosition(VgPosition pPosition);
}

./Common/Makefiles/Android/src/com/visioglobe/VisioSample/Interfaces/VgMyLocationProvider.java

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

package com.visioglobe.VisioSample.Interfaces;

public interface VgMyLocationProvider 
{
     public void enable();

     public void disable();
     
     public boolean isEnabled();

     public void setListener(VgMyLocationListener pListener);

    public void release();
    
}

iOS/Qt Specific Files

./navigationModule/Inc/Apple/VgMyAppDelegate.h

/*
 * Copyright 2011, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */
#import <UIKit/UIKit.h>

@class VgMyViewController;

@interface VgMyAppDelegate : NSObject< UIApplicationDelegate > {
    UIWindow* window;
    VgMyViewController* viewController;
}

@property (nonatomic, retain) IBOutlet UIWindow* window;
@property (nonatomic, retain) IBOutlet VgMyViewController* viewController;

@end

./navigationModule/Inc/Apple/VgMyViewController.h

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

#import <UIKit/UIKit.h>
#include <string>

#import "VgMyConfigPreferences.h"

class VgMyViewControllerImpl;
@class VgEAGLView;
class VgMyInstructionViewWrapper;
@class VgMySimulatedLocationProvider;
class VgMyRemoteMapManager;
class VgMySwitchViewsListener;

@interface VgMyViewController : UIViewController
{
    VgMyViewControllerImpl* mVgMyViewControllerImpl;
    
    VgEAGLView* mMapView;
    
    UISwitch* mSimulatePositionSwitch;
    UISwitch* mAvoidStairsRoutingSwitch;
    UIButton* mSwitchViewsButton;

    VgMySimulatedLocationProvider* mLocationProvider;
    VgMyRemoteMapManager* mVgMyRemoteMapManager;
    UIProgressView* mProgressView;
    
    VgMyConfigPreferences* mConfigPreferences;
    VgMySwitchViewsListener* mVgMySwitchViewsListener;
}
@property (retain) IBOutlet VgEAGLView* mMapView;
@property (retain) IBOutlet UISwitch* mSimulatePositionSwitch;
@property (retain) IBOutlet UISwitch* mAvoidStairsRoutingSwitch;
@property (retain) UIProgressView* mProgressView;
@property (retain) IBOutlet UIButton* mSwitchViewsButton;

@property (retain) VgMyConfigPreferences* mConfigPreferences;

-(IBAction) switchToGlobalView:(id)sender;


-(IBAction) clearRoute:(id)sender;
-(IBAction) simulatePosition:(id)sender;
-(IBAction)toggleAvoidStairsRouting:(UISwitch*)sender;

-(IBAction) loadFromNetwork:(id)sender;

-(IBAction) resetConfigPreferences:(id)sender;

-(BOOL)verifyMap:(VgMyConfigPreferences*)pConfig withOutputErrorStr:(std::string&)pOutErrorStr;


// Compares two map bundle versions and determines whether the first version is
// older then the second version.
// @returns Returns YES, if pVersion1 is older than pVersion2, otherwise NO.
+(Boolean)isVersion:(NSString*)pVersion1 olderThan:(NSString*)pVersion2;

-(BOOL)loadMap:(VgMyConfigPreferences*)pConfig;
- (void)unloadMap;

// This needs to be called when ever the mMapView changes size
// to update the stackview parameters
-(void)updateMapViewParameters;

-(void)startProgress;
-(void)progress:(int)pReceived outOf:(int)pTotal;
-(void)doneProgress;
@end

./navigationModule/Src/Apple/VgMyAppDelegate.mm

/*
 * Copyright 2011, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

#import "VgMyAppDelegate.h"
#import "VgMyViewController.h"

@implementation VgMyAppDelegate

@synthesize window;
@synthesize viewController;

-(void) applicationDidFinishLaunching:(UIApplication*)application
{
    // create the window, no need for MainWindow*.nib, works on iphone, iphone5 and ipad.
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    
    NSString* lNibName = @"VgMyViewController";
#ifdef __IPHONE_3_2
    // we know we are in new SDK
    if ( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad )
    {
        lNibName = @"VgMyViewController~iPad";
    }
    else
    {
        lNibName = @"VgMyViewController";
    }
#endif
    self.viewController = [[VgMyViewController alloc] initWithNibName:lNibName bundle:nil];

    if ([self.window respondsToSelector:@selector(setRootViewController:)])
    {
        // iOS 4+
        self.window.rootViewController = viewController;
    }
    else
    {
        // iOS 3
        [window addSubview : viewController.view];
        [window sendSubviewToBack:viewController.view];
    }
    
    [window makeKeyAndVisible];
}

-(void) dealloc
{
    [viewController release];
    [window release];
    [super dealloc];
}

@end

./navigationModule/Src/Apple/VgMyViewController.mm

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 * 
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 * 
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 * 
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 * 
 * Contact information:  Visioglobe SAS, 
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

#import "VgMyViewController.h"

#import "Apple/VgEAGLView.h"
#import <QuartzCore/QuartzCore.h>

#include "VgApplication/VgIApplication.h"
#include "VgApplication/VgIModule.h"
#include "VgApplication/VgIManipulatorManager.h"
#include "VgApplication/VgIModuleManager.h"

#include "VgEngine/VgIEngine.h"
#include "VgEngine/VgILicenseManager.h"
#include "VgEngine/VgICamera.h"
#include "VgEngine/VgIDatabase.h"

#include "Modules/3D/VgIGeometryCallback.h"
#include "Modules/3D/VgIGeometryEvent.h"

#ifdef VG_MAP_MODULE
#include "Modules/Map/VgIMapModule.h"
#include "Modules/Map/VgIPlaceListener.h"
#include "Modules/Map/VgPlaceDescriptor.h"
#endif // VG_MAP_MODULE

#ifdef VG_ROUTING_MODULE
#include "Modules/Routing/VgIRoutingModule.h"
#endif // VG_MAP_MODULE

#ifdef VG_ROUTING_MODULE
#include "Modules/Navigation/VgINavigationModule.h"
#endif // VG_MAP_MODULE

#include "VgMyBasicApplicationController.h"
#include "VgMyStackedLayerAndCameraHandler.h"
#include "VgMyRoutingHelper.h"
#include "VgMyNavigationHelper.h"
#include "VgMyInstructionPathDisplay.h"
#include "VgMyTextureLoader.h"
#include "VgMyAvatarDisplay.h"
#include "VgMyPlaceConfigurationSetter.h"

#import "VgMyMapPlaceListenerWithBubble.h"
#import "VgMyInstructionView.h"
#import "VgMyFloorSliderView.h"
#import "VgMySimulatedLocationProvider.h"

#include "VgMyRemoteMapManager.h"


class VgMyInstructionViewWrapper : public VgMyInstructionDisplay
{
public:
    VgMyInstructionViewWrapper(VgMyInstructionView *pInstructionView)
    {
        mInstructionView = pInstructionView;
        [mInstructionView retain];
    }
    ~VgMyInstructionViewWrapper()
    {
        [mInstructionView release];
        mInstructionView = NULL;
    }
    virtual void updateWithInstruction(VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigation > const& pNavigation, unsigned int pIndex)
    {
        [mInstructionView notifyNewInstruction:pNavigation withIndex:pIndex];
    }
        
    virtual void clear()
    {
        
    }
    
    virtual void show()
    {
        mInstructionView.hidden = NO;
    }
    
    virtual void hide()
    {
        mInstructionView.hidden = YES;
    }
    
    virtual bool isVisible()
    {
        return (mInstructionView.hidden == NO);
    }
    
    VgMyInstructionView* mInstructionView;
};



class VgFloorSliderWrapper : public VgMyLayerAndCameraListener, public VgMyDisplayable
{
public:
    // Assumes VgMyFloorSliderView has been already initialized with the right number of floors
    VgFloorSliderWrapper(VgMyFloorSliderView *pVgFloorSlider)
    {
        mVgFloorSlider = pVgFloorSlider;
        [mVgFloorSlider retain];
    }
    ~VgFloorSliderWrapper()
    {
        [mVgFloorSlider removeFromSuperview];
        [mVgFloorSlider release];
        mVgFloorSlider = NULL;
    }

    virtual void layerWillChangeFrom(VgMyLayerAndCameraHandler* pSender, const std::string& pFloorFrom, const std::string& pFloorTo)
    {
        // need to find index of layername pFloorTo;
        int lIndex = 0;
        std::string lLayerName;
        while (pSender->getLayerName(lIndex, lLayerName))
        {
            if (lLayerName == pFloorTo)
            {
                [mVgFloorSlider setCurrentFloorIndex:lIndex];
                return;
            }
            lIndex++;
        }
    }
    
    virtual void layerChangedTo(VgMyLayerAndCameraHandler* pSender, const std::string& pFloorFrom, const std::string& pFloorTo)
    {
    }
    
    virtual void viewWillChange(VgMyLayerAndCameraHandler* pSender, const bool pDoesChangeFromGlobalToDetailed)
    {
    }
    virtual void viewDidChange(VgMyLayerAndCameraHandler* pSender, const bool pDoesChangeFromGlobalToDetailed)
    {
    }
    
    virtual void clear()
    {
        
    }
    
    virtual void show()
    {
        mVgFloorSlider.hidden = NO;
    }
    
    virtual void hide()
    {
        mVgFloorSlider.hidden = YES;
    }
    
    virtual bool isVisible()
    {
        return (mVgFloorSlider.hidden == NO);
    }
    
    VgMyFloorSliderView* mVgFloorSlider;
};

class VgMyViewControllerImpl /*:  public VgMyRouteCreator*/
{
public:
    
    VgMyViewControllerImpl(VgEAGLView* pMapView);
    
    ~VgMyViewControllerImpl();
    
    bool loadConfiguration(const std::string& pConfiguration, const int pSecretKey, const std::string& pLicenseURL);

    void onToggleInjectPosition(bool pValue);
    
    void onClearRoute();
    
    VgApplication::VgIApplication* mVgApplication;
    
    VgMyBasicApplicationController* mController;                
    
    VgEAGLView* mMapView;                                    

    VgEngine::VgRefPtr< VgMyMapPlaceListenerWithBubble > mSamplePlaceListenerWithBubble;
    
    VgMyPlaceConfigurationSetter* mPlaceConfig;
    
    VgEngine::VgRefPtr< Vg3DModule::VgIGeometryCallback > mStartPointCallback; 
    VgMyStackedLayerAndCameraHandler* mLayerAndCameraHandler;

    VgFloorSliderWrapper* mVgFloorSliderWrapper;
    
    VgMyRoutingHelper* mRoutingHelper;
    
    VgMyNavigationHelper* mNavigationHelper;
    
    VgMyInstructionPathDisplay* mInstructionPathDisplay;
    
    VgMyInstructionViewWrapper* mVgMyInstructionViewWrapper;
    
    VgMyTextureLoader* mTextureLoader;
    
    VgMyAvatarDisplay* mAvatarDisplay;
    VgMyAvatarDisplay* mAvatarOnRouteDisplay;

    void configureStackedLayerAndCameraHandler();
    
};

VgMyViewControllerImpl::VgMyViewControllerImpl(VgEAGLView* pMapView)
: 
 mController(NULL)
, mLayerAndCameraHandler(NULL)
, mRoutingHelper(NULL)
, mNavigationHelper(NULL)
, mVgMyInstructionViewWrapper(NULL)
, mInstructionPathDisplay(NULL)
, mVgFloorSliderWrapper(NULL)
, mTextureLoader(NULL)
, mAvatarDisplay(NULL)
, mAvatarOnRouteDisplay(NULL)
, mMapView(pMapView)
, mPlaceConfig(NULL)
{
    
    VgApplication::VgIApplication* lVgApplication = mVgApplication = [pMapView getApplication];
    
    const std::string lVisioDevKitVersion = mVgApplication->editEngine()->editLicenseManager()->getVersion();
    NSLog(@"VisioDevKit version: %s", lVisioDevKitVersion.c_str());
    
    NSString* lPath = [[NSBundle mainBundle] executablePath];
    const std::string lImageResourcesDirectory = std::string([[lPath stringByDeletingLastPathComponent] UTF8String]) + std::string("/");

    mTextureLoader = new VgMyTextureLoader(lVgApplication, lImageResourcesDirectory);
    
    mController = new VgMyBasicApplicationController(*lVgApplication, mTextureLoader);
    
}
bool VgMyViewControllerImpl::loadConfiguration(const std::string& pConfiguration, const int pSecretKey, const std::string& pLicenseURL)
{
    
    if ( !mController->loadConfiguration(pConfiguration, pSecretKey, pLicenseURL, 0))
    {
        return false;
    }
    
    CGRect lMapViewFrame = mMapView.frame;

    VgApplication::VgIApplication* lVgApplication = mVgApplication = [mMapView getApplication];
    
    mLayerAndCameraHandler = new VgMyStackedLayerAndCameraHandler(lVgApplication, mController, lMapViewFrame.size.width, lMapViewFrame.size.height);
    
    mController->setLayerAndCameraHandler(mLayerAndCameraHandler);
    
    configureStackedLayerAndCameraHandler();

    unsigned int lNumOfLayers = mController->getNumberOfLayers();
    bool lAddFloorSlider = true;
    if (lAddFloorSlider && lNumOfLayers > 1)
    {
        CGRect lFrame = mMapView.frame;
        VgMyFloorSliderView *lFloorSliderView = [[VgMyFloorSliderView alloc] initWithFrame:lFrame
                                                        andLayerCameraHandler:mController];
        [lFloorSliderView setNumberOfFloors:lNumOfLayers];
        [lFloorSliderView setCurrentFloorIndex:0];
        lFloorSliderView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin |
        UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
        [mMapView.superview addSubview:lFloorSliderView];
        mVgFloorSliderWrapper = new VgFloorSliderWrapper(lFloorSliderView);
        [lFloorSliderView release];
        
        mController->addLayerAndCameraListener(mVgFloorSliderWrapper);
    }
    
    if (mController->hasMapModule())
    {
        VgMapModule::VgIMapModule* lMapModule = static_cast< VgMapModule::VgIMapModule* >(lVgApplication->editModuleManager()->queryModule("Map"));
        
        // configure place related information.
        NSString* lPath = [[NSBundle mainBundle] executablePath];
        const std::string lResourcesDirectory = std::string([[lPath stringByDeletingLastPathComponent] UTF8String]) + std::string("/");
        mPlaceConfig = new VgMyPlaceConfigurationSetter(mTextureLoader, lVgApplication->editEngine(), lResourcesDirectory);
        mPlaceConfig->configurePlaces(lMapModule);

        // Add a listener that will be notified when a place is clicked.
        mSamplePlaceListenerWithBubble = new VgMyMapPlaceListenerWithBubble(mMapView,mController);
        // we add mSamplePlaceListenerWithBubble as a listener to LayerAndCamera events, to
        // disable activating the bubble in global view.
        mController->addLayerAndCameraListener(mSamplePlaceListenerWithBubble.get());
        
        if (mController->hasRoutingModule())
        {
            mRoutingHelper = new VgMyRoutingHelper(lVgApplication, mTextureLoader, mController->getRouteCallback(), mLayerAndCameraHandler);

            // we add mRoutingHelper as RouteCreator as well as RouteDisplayer
            mController->setRouteCreator(mRoutingHelper);
            mController->addRouteDisplay(mRoutingHelper);
            
            if (mController->hasNavigationModule())
            {
                mNavigationHelper = new VgMyNavigationHelper(static_cast<VgNavigationModule::VgINavigationModule*>(lVgApplication->editModuleManager()->queryModule("Navigation")));
                mController->setNavigationCreator(mNavigationHelper);
                
                // This highlights the current segment of the navigation.
                bool lShowNavigationSegmentDebug = false;
                if (lShowNavigationSegmentDebug)
                {
                    mInstructionPathDisplay = new VgMyInstructionPathDisplay(lVgApplication);
                    mController->addInstructionDisplay(mInstructionPathDisplay);
                }
                
                VgMyInstructionView* lInstructionView = [[VgMyInstructionView alloc] initWithFrame:CGRectMake(0, 0, mMapView.frame.size.width, HEIGHT_INSTRUCTION_VIEW) withApplication:mVgApplication withUpdateListener:mController];
                [mMapView addSubview:lInstructionView];
                // the wrapper will retain the view.
                mVgMyInstructionViewWrapper = new VgMyInstructionViewWrapper(lInstructionView);
                // Hide the instructin view, at first, the first message will make it appear.
                mVgMyInstructionViewWrapper->hide();
                
                mController->addInstructionDisplay(mVgMyInstructionViewWrapper);
                
                mAvatarDisplay = new VgMyAvatarDisplay(lVgApplication, mTextureLoader, false);
                mAvatarOnRouteDisplay = new VgMyAvatarDisplay(lVgApplication, mTextureLoader, true);
                
                mController->addNavigationPositionDisplay(mAvatarDisplay);
                mController->addNavigationPositionDisplay(mAvatarOnRouteDisplay);
            }
        }
    }
    
    // Select View mode : global or detailed
    if (lNumOfLayers > 1)
    {
        mLayerAndCameraHandler->switchToGlobalView();
    }
    else
    {
        // if we only have one floor, avoid displaying global view.
        mLayerAndCameraHandler->switchToDetailedView();
    }
    
    return true;
}

VgMyViewControllerImpl::~VgMyViewControllerImpl()
{
    if (mController->hasMapModule())
    {
        VgMapModule::VgIMapModule* lMapModule = static_cast< VgMapModule::VgIMapModule* >(mVgApplication->editModuleManager()->queryModule("Map"));

        lMapModule->removeListener(mSamplePlaceListenerWithBubble);
        mSamplePlaceListenerWithBubble = NULL;
    }
    
    delete mController;
    delete mLayerAndCameraHandler;
    delete mRoutingHelper;
    delete mNavigationHelper;
    delete mTextureLoader;
    delete mAvatarDisplay;
    delete mAvatarOnRouteDisplay;
    mStartPointCallback = NULL;
    delete mInstructionPathDisplay;
    delete mVgMyInstructionViewWrapper;
    delete mVgFloorSliderWrapper;    
    delete mPlaceConfig;
}


void VgMyViewControllerImpl::onClearRoute()
{
    if (mSamplePlaceListenerWithBubble.isValid())
    {
        mSamplePlaceListenerWithBubble->hideBubble();
    }
    
    if (mVgMyInstructionViewWrapper)
    {
        mVgMyInstructionViewWrapper->hide();
    }
    
    mController->deleteRoute();
}






// Configure VgMyStackedLayerAndCameraHandler parameters
// For a list of what paramters are configurable, please see
// VgMyStackedLayerAndCameraHandler
void VgMyViewControllerImpl::configureStackedLayerAndCameraHandler()
{
    // IMPORTANT
    // These parameters are chosen specifically for the Visioglobe Map Generic sample
    // If developing with a different map bundle then there are two choices:
    // 1/ comment the below configurations.  VgMyStackedLayerAndCameraHandler will
    // automatically calculate values which 'should' work for the map bundle.
    // 2/ change the configurations below to work with the map bundle.
    mLayerAndCameraHandler->setParam(VgMyStackedLayerAndCameraHandler::eLayerMaxSize, 700);
    mLayerAndCameraHandler->setParam(VgMyStackedLayerAndCameraHandler::eStackViewHeading, -68);
    mLayerAndCameraHandler->setParam(VgMyStackedLayerAndCameraHandler::eLayerDistance, 30);
    mLayerAndCameraHandler->setParam(VgMyStackedLayerAndCameraHandler::eLayerDistanceFromCurrent, 170);
    
    // Force the stack view to update
    mLayerAndCameraHandler->refreshStackView();
}

// This class adds and remove a button as a function of which mode (global or detailed) we are in.
class VgMySwitchViewsListener : public VgMyLayerAndCameraListener
{
    VgMyViewController* mVgMyViewController;
    VgMapModule::VgIMapModule* mMapModule;
public:
    VgMySwitchViewsListener(VgMyViewController* pVgMyViewController) : mVgMyViewController(pVgMyViewController ) {};
    
    virtual void viewWillChange(VgMyLayerAndCameraHandler* pSender, const bool pDoesChangeFromGlobalToDetailed)
    {
        UIButton* lButton = mVgMyViewController.mSwitchViewsButton;
        
        if (pDoesChangeFromGlobalToDetailed)
        {
            lButton.hidden = NO;
            lButton.userInteractionEnabled = NO;
            lButton.alpha = 0.0;
            [UIView animateWithDuration:1.0
                                  delay:1.0
                                options: UIViewAnimationCurveEaseInOut
                             animations:^{lButton.alpha = 1.0;}
                             completion:^(BOOL){ 
                                 lButton.userInteractionEnabled = YES;
                                 lButton.hidden = NO;
                                 lButton.alpha = 1.0;
                             }];
        }
        else
        {
            lButton.alpha = 1.0;
            lButton.userInteractionEnabled = NO;
            [UIView animateWithDuration:2.0
                                  delay:0.0
                                options: UIViewAnimationCurveEaseInOut
                             animations:^{lButton.alpha = 0.0;}
                             completion:^(BOOL){lButton.hidden = YES;}];
        }
    }
    
    void viewDidChange(VgMyLayerAndCameraHandler* pSender, const bool pDoesChangeFromGlobalToDetailed)
    {
        if (pDoesChangeFromGlobalToDetailed)
        {
            // make the button clickable as soon as it is useful.
            mVgMyViewController.mSwitchViewsButton.userInteractionEnabled = YES;
        }
    }

    
    virtual void layerWillChangeFrom(VgMyLayerAndCameraHandler* pSender, const std::string& pFloorFrom, const std::string& pFloorTo)
    {
        
    }
    virtual void layerChangedTo(VgMyLayerAndCameraHandler* pSender, const std::string& pFloorFrom, const std::string& pFloorTo)
    {
        
    }
};

class VgMyControllerRemoteMapManagerCallback;


// if user clicks ok, call pCallback->proceedWithDownload();
@interface VgMyMapManagerDialog : NSObject<UIAlertViewDelegate>
{
    VgMyControllerRemoteMapManagerCallback* mCallback;
}
-(id)initMapCallback:(VgMyControllerRemoteMapManagerCallback*)pCallback;
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex;
@end

class VgMyControllerRemoteMapManagerCallback : public VgMyRemoteMapManagerCallback
{
    VgMyViewController* mMyViewController;
    std::string mMapName;
    VgMyMapManagerListParser::Entry mEntry;
    VgMyRemoteMapManager* mRemoteMapManager;
    
    VgMyMapManagerDialog *mDialogDelegate; // we manage it by hand.
    
public:
    VgMyControllerRemoteMapManagerCallback(VgMyViewController* pMyViewController,
                                           const std::string& pMapName)
    {
        mMapName = pMapName;
        mMyViewController = pMyViewController;
        mRemoteMapManager = NULL;
        mDialogDelegate = nil;
    }
    virtual ~VgMyControllerRemoteMapManagerCallback()
    {
        if (mDialogDelegate)
        {
            [mDialogDelegate release];
            mDialogDelegate = nil;
        }
    }
    
    virtual void proceedWithDownload()
    {
        //bool lStatus = pRemoteMapManager->downloadBuffer(mEntry.mID);
        [mMyViewController startProgress];
        bool lStatus = mRemoteMapManager->downloadMap(mEntry.mID);
        if (lStatus == false)
        {
            // there was an error sending the request.  generally there is download already in place.
        }
    }
    
    virtual void listFinished(VgMyRemoteMapManager* pRemoteMapManager, ErrorCode pErrorCode, VgMyMapManagerListParser* pListParser)
    {
        mRemoteMapManager = pRemoteMapManager;
        // reset the entry.
        mEntry = VgMyMapManagerListParser::Entry();
        
        if (pErrorCode == eSuccess && pListParser != NULL && pListParser->isValid())
        {
            while ( ! pListParser->finished())
            {
                VgMyMapManagerListParser::Entry lEntry = pListParser->getNext();
                
                if (lEntry.mValid)
                {
                    VgMyConfigPreferences* lPreferences = mMyViewController.mConfigPreferences;
                    
                    if (lEntry.mName.find(mMapName) != std::string::npos)
                    {
                        if ((lPreferences.version == nil) ||
                            ([VgMyViewController isVersion:lPreferences.version olderThan:[NSString stringWithUTF8String:lEntry.mVersion.c_str()]]) )
                        {
                            mEntry = lEntry;
                            if (mDialogDelegate)
                            {
                                [mDialogDelegate release];
                                mDialogDelegate = nil;
                            }
                            mDialogDelegate = [[VgMyMapManagerDialog alloc] initMapCallback:this];
                            UIAlertView* lAlert = [[UIAlertView alloc] initWithTitle:@"Notice"
                                                                             message:@"There is a more recent map, do you want to download it?"
                                                                            delegate:mDialogDelegate
                                                                   cancelButtonTitle:@"Cancel"
                                                                   otherButtonTitles:@"OK",nil];
                            [lAlert show];
                            [lAlert release];
                            

                        }
                        else
                        {
                            UIAlertView* lAlert = [[UIAlertView alloc] initWithTitle:@"Notice"
                                                                             message:@"You already have the latest map"
                                                                            delegate:nil
                                                                   cancelButtonTitle:@"Cancel"
                                                                   otherButtonTitles:nil];
                            [lAlert show];
                            [lAlert release];
                        }
                        // make sure we can do this.
                        return;
                    }
                }
            }
        }
        
        // TODO: localize this messages
        NSString* lMsg;
        if (pErrorCode == eSuccess)
        {
            lMsg = @"List succeded, but map not found";
        }
        else
        {
            lMsg = @"List Failed";
        }
        
        UIAlertView* lAlert = [[UIAlertView alloc] initWithTitle:@"Error" message:lMsg
                                                        delegate:nil cancelButtonTitle:@"Cancel" otherButtonTitles:nil];
        [lAlert show];
        [lAlert release];
        
    }
    
    virtual void mapDownloadProgress(VgMyRemoteMapManager* pRemoteMapManager, int pDownloaded,int pTotal)
    {
        [mMyViewController progress:pDownloaded outOf:pTotal];
        // normally update progress bar.
    }
    
    virtual void mapDownloadFinished(VgMyRemoteMapManager* pRemoteMapManager, ErrorCode pErrorCode, unsigned int pMapID)
    {
        [mMyViewController doneProgress];
        if (pErrorCode == eSuccess)
        {
            
            std::string lConfigurationPath;
            if (pRemoteMapManager->getLocalConfigPathForMap(pMapID, lConfigurationPath))
            {
                NSString *mapFilePath = [NSString stringWithUTF8String:lConfigurationPath.c_str()];
                
                VgMyConfigPreferences* lPreferences = [[[VgMyConfigPreferences alloc] init] autorelease];
                lPreferences.configurationFile = mapFilePath;
                lPreferences.secret = mEntry.mSecretCode;
                lPreferences.licenseURL = [NSString stringWithFormat:@"http://license.visioglobe.com/renew/%s",mEntry.mLicenseID.c_str()];
                lPreferences.version = [NSString stringWithUTF8String:mEntry.mVersion.c_str()];
                std::string lErrorStr;
                if ([mMyViewController verifyMap:lPreferences withOutputErrorStr:lErrorStr])
                {
                    [mMyViewController unloadMap];
                    [mMyViewController loadMap:lPreferences];
                    // save the preferences if they are good.
                    [lPreferences save];
                    mMyViewController.mConfigPreferences = lPreferences;
                }
                else
                {
                    NSString* lMsg = [NSString stringWithFormat:@"loadConfiguration failed %s", lErrorStr.c_str()];
                    
                    UIAlertView* lAlert = [[UIAlertView alloc] initWithTitle:@"Error" message:lMsg
                                                                    delegate:nil cancelButtonTitle:@"Cancel" otherButtonTitles:nil];
                    [lAlert show];
                    [lAlert release];
                }
                return;
            }
            
        }
        
        UIAlertView* lAlert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Download Failed"
                                                        delegate:nil cancelButtonTitle:@"Cancel" otherButtonTitles:nil];
        [lAlert show];
        [lAlert release];
    }
};


@implementation VgMyMapManagerDialog


-(id)initMapCallback:(VgMyControllerRemoteMapManagerCallback*)pCallback
{
    self = [super init];
    if (self)
    {
        mCallback = pCallback;
    }
    return self;
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (buttonIndex == 1)
    {
        mCallback->proceedWithDownload();
    }
}
-(void)dealloc
{
    [super dealloc];
}
@end
@interface VgMyViewController ()

@end

@implementation VgMyViewController

@synthesize mMapView;
@synthesize mSimulatePositionSwitch;
@synthesize mAvoidStairsRoutingSwitch;
@synthesize mSwitchViewsButton;
@synthesize mProgressView;
@synthesize mConfigPreferences;


typedef std::vector< std::string > stringvector;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        mVgMyViewControllerImpl = NULL;
        mVgMyRemoteMapManager = NULL;
        mProgressView = nil;
        mVgMySwitchViewsListener = NULL;
        
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleWillResign:) name:UIApplicationWillResignActiveNotification object:nil];

        // Custom initialization
    }
    return self;
}

-(void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];

    self.mProgressView = nil;

    [self unloadMap];
    
    delete mVgMyRemoteMapManager;
    mVgMyRemoteMapManager = NULL;

    [super dealloc];
    
}


-(BOOL)verifyMap:(VgMyConfigPreferences*)pConfig withOutputErrorStr:(std::string&)pOutErrorStr
{
    BOOL lSuccess = NO;
    CGRect lFrame;
    lFrame.size.width = 32;
    lFrame.size.height = 32;
    
    VgEAGLView* lMap = [[VgEAGLView alloc] initWithFrame:lFrame];
    [lMap startAnimation];
    
    VgApplication::VgIApplication* lVgApplication = [lMap getApplication];
    
    unsigned int lSecret = pConfig.secret;
    std::string pConfiguratioFileStr = std::string([pConfig.configurationFile UTF8String]);
    std::string pLicenseURLStr = std::string([pConfig.licenseURL UTF8String]);

    if (lVgApplication->editEngine()->editDatabase()->loadConfiguration(pConfiguratioFileStr, lSecret, pLicenseURLStr))
    {
        lSuccess = YES;
    }
    else
    {
        VgEngine::VgErrorCode lErrorCode = lVgApplication->editEngine()->getLastError();
        const std::string& lErrorStr = lVgApplication->editEngine()->getErrorString(lErrorCode);
        pOutErrorStr = lErrorStr;
    }
    
    [lMap release];
    return lSuccess;

}

- (BOOL)loadMap:(VgMyConfigPreferences*)pConfig
{
    VgEAGLView* lMap = mMapView;
    
    if (mVgMyViewControllerImpl == NULL)
    {
        mVgMyViewControllerImpl = new VgMyViewControllerImpl(lMap);
        unsigned int lSecret = pConfig.secret;
        std::string pConfiguratioFileStr = std::string([pConfig.configurationFile UTF8String]);
        std::string pLicenseURLStr = std::string([pConfig.licenseURL UTF8String]);
        if (mVgMyViewControllerImpl->loadConfiguration(pConfiguratioFileStr, lSecret, pLicenseURLStr) == false)
        {
            VgApplication::VgIApplication* lVgApplication = [mMapView getApplication];

            VgEngine::VgErrorCode lErrorCode = lVgApplication->editEngine()->getLastError();
            const std::string& lErrorStr = lVgApplication->editEngine()->getErrorString(lErrorCode);
            
            NSString* lMsg = [NSString stringWithFormat:@"loadConfiguration failed %s", lErrorStr.c_str()];
            
            UIAlertView* lAlert = [[UIAlertView alloc] initWithTitle:@"Error" message:lMsg
                                                            delegate:nil cancelButtonTitle:@"Cancel" otherButtonTitles:nil];
            [lAlert show];
            [lAlert release];
            
            // destroy the object to avoid using the mVgMyViewControllerImpl when no dataset loaded.  Fixes a crash where a local invalid license at start would cause someone to use mVgMyViewControllerImpl without a loaded configuration.
            delete mVgMyViewControllerImpl;
            mVgMyViewControllerImpl = NULL;
            return NO;
        }
            
        if (mVgMyViewControllerImpl->mController != NULL && mVgMyViewControllerImpl->mLayerAndCameraHandler != NULL)
        {
            mLocationProvider = [[VgMySimulatedLocationProvider alloc] initWithApplication:[mMapView getApplication] withLayerAndCameraHandler:mVgMyViewControllerImpl->mLayerAndCameraHandler];
            [mLocationProvider setListener:mVgMyViewControllerImpl->mController];
        }
    }
    
    if (mVgMyViewControllerImpl->mController != NULL && mVgMyViewControllerImpl->mController->hasRoutingModule())
    {
        mAvoidStairsRoutingSwitch.hidden = NO;
    }
    else
    {
        mAvoidStairsRoutingSwitch.hidden = YES;
    }
    
    // change global view to floor level with one click:
    // in detailed view: show a button to switch to global view.
    // in global view: do not show button
    // if we only have one layer, do not even add the handler to prevent user from reaching global view.
    if (mVgMyViewControllerImpl->mController && mVgMyViewControllerImpl->mController->getNumberOfLayers() > 1)
    {
        mVgMySwitchViewsListener = new VgMySwitchViewsListener(self);
        mVgMyViewControllerImpl->mController->addLayerAndCameraListener(mVgMySwitchViewsListener);
    }
    
    [self updateMapViewParameters];
    
    return YES;
}

+(Boolean)isVersion:(NSString*)pVersion1 olderThan:(NSString*)pVersion2
{
    Boolean lResult = NO;
    
    NSInteger lCompareResult = [pVersion1 compare:pVersion2];
    
    // If the left operand is smaller than the right operand.
    if(NSOrderedAscending == lCompareResult)
    {
        lResult = YES;
    }
    
    return lResult;
}


- (void)unloadMap
{
    if (mVgMyViewControllerImpl)
    {
        mVgMyViewControllerImpl->onClearRoute();
    }

    [mLocationProvider disable];
    [mLocationProvider autorelease];
    mLocationProvider = nil;
    
    delete mVgMyViewControllerImpl;
    mVgMyViewControllerImpl = NULL;
    
    delete mVgMySwitchViewsListener;
    mVgMySwitchViewsListener = NULL;
}

-(void)updateMapViewParameters
{
    if (mVgMyViewControllerImpl)
    {
        CGRect lMapViewFrame = mMapView.frame;
        mVgMyViewControllerImpl->mLayerAndCameraHandler->refreshParameters(lMapViewFrame.size.width,
                                                                           lMapViewFrame.size.height);
        // reload our personal stacked layer and camera handler settings.
        mVgMyViewControllerImpl->configureStackedLayerAndCameraHandler();
    }
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // If you wanted to turn off multisampling for any reason.
    // There is pratically no performance hit and the diagonal lines look better
    //mMapView.multisample = NO;
    
    // We do startAnimation so the next [mMapView getApplication] returns a valid VgIApplication.
    [mMapView startAnimation];

    mSwitchViewsButton.hidden = YES;
    
    // Do any additional setup after loading the view.
    // In this example the mMapView is created via the xib file.
    // It could also be created programmatically.
    // Note that if the VgEAGLView is created via a nib file, it is possible
    // for it to be deallocated and recreated from nib under low memory condition
    // or when the ViewController is no longer visible.
    // In that case it is better to create the VgEAGLView programmatically.
    
    
    // IMPORTANT:
    // The below map config details refer to the map embedded within your application.
    // The integrator is responsible for updating these values to correctly correspond with
    // the map embedded within the application.
    VgMyConfigPreferences* lEmbeddedMapConfig = [[VgMyConfigPreferences alloc] init];
    lEmbeddedMapConfig.secret = 0;
    lEmbeddedMapConfig.configurationFile = @"Data/PVRTC/vg_config.xml";
    lEmbeddedMapConfig.licenseURL = @"http://license.visioglobe.com/renew/";
    lEmbeddedMapConfig.version = @"20120905";
    
    
    // Retrieve the current map configuration from preferences.
    self.mConfigPreferences = [VgMyConfigPreferences getFromPreferences];
    
    // If there is no map config stored in preferences
    if((nil == self.mConfigPreferences) ||
       (YES == [VgMyViewController isVersion:self.mConfigPreferences.version olderThan:lEmbeddedMapConfig.version] ) )
    {
        // Then use the embedded map configuration
        self.mConfigPreferences = lEmbeddedMapConfig;
    }

    
    // Load the local map
    // Note: it may be the embedded map OR a map which has been downloaded from the network
    [self loadMap:self.mConfigPreferences];

    // Check the network to see if a newer map bundle is
    [self loadFromNetwork:nil];
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

// Override to allow orientations other than the default portrait orientation.
-(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return YES;
}

-(void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
    // Rotation has completed.  Use self.interfaceOrientation to find out new orientation.
    [mMapView setInterfaceOrientation : self.interfaceOrientation];
    [self updateMapViewParameters];
}


-(void) viewWillAppear:(BOOL)animated
{
    // do rendering while is this view.
    [mMapView setRenderSuspended : NO];
}
-(void)viewDidAppear:(BOOL)animated
{
    [self updateMapViewParameters];
}

-(void) viewDidDisappear:(BOOL)animated
{
    // do not render while the view is hidden.
    [mMapView setRenderSuspended : YES];
}

// We don't want to render when we are not active (it can stop the application if we do).
-(void) handleDidBecomeActive:(id)pSender
{
    [mMapView setRenderSuspended : NO];
}

-(void) handleWillResign:(id)pSender
{
    [mMapView setRenderSuspended : YES];
}

-(void) didReceiveMemoryWarning
{
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
    [mMapView notifyDidReceiveMemoryWarning];
    // Release any cached data, images, etc that aren't in use.
}


-(IBAction)clearRoute:(id)sender
{
    mVgMyViewControllerImpl->onClearRoute();
}


-(IBAction)switchViews:(id)sender
{
    if (mVgMyViewControllerImpl == NULL || mVgMyViewControllerImpl->mController == NULL)
    {
        return;
    }
    
    if(mVgMyViewControllerImpl->mController->isGlobalView() == true)
    {
        mVgMyViewControllerImpl->mController->switchToDetailedView();
    }
    else
    {
        mVgMyViewControllerImpl->mController->switchToGlobalView();
    }
}


-(IBAction)simulatePosition:(UISwitch*)sender
{
    const bool pValue = [sender isOn];

    if (pValue)
    {
        [mLocationProvider enable];
    }
    else
    {
        [mLocationProvider disable];
        mVgMyViewControllerImpl->mController->clearNavigationPositionDisplays();
    }
}

-(IBAction)toggleAvoidStairsRouting:(UISwitch*)sender
{
    const bool pValue = [sender isOn];
    
    if (mVgMyViewControllerImpl == NULL) return;
    
    if (mVgMyViewControllerImpl->mController)
    {
        return mVgMyViewControllerImpl->mController->setAvoidStairs(pValue);
    }
}

-(void)startProgress;
{
    self.mProgressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleBar];
    
    CGRect lMapFrame = mMapView.frame;
    CGRect lProgressFrame = mProgressView.frame;
    lProgressFrame.origin.x = (lMapFrame.size.width - lProgressFrame.size.width) / 2;
    //lProgressFrame.origin.y = (lMapFrame.size.height - lProgressFrame.size.height) / 2;
    lProgressFrame.origin.y = (lProgressFrame.size.height);
    mProgressView.frame = lProgressFrame;
    mProgressView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin;
    [mMapView addSubview:self.mProgressView];
}

-(void)progress:(int)pReceived outOf:(int)pTotal
{
    float lPercentage = (float)pReceived/(float)pTotal;
    self.mProgressView.progress = lPercentage;
}

-(void)doneProgress
{
    [mProgressView removeFromSuperview];
    self.mProgressView = nil;
}

-(IBAction)resetConfigPreferences:(id)sender
{
    [VgMyConfigPreferences reset];
    
    NSLog(@"simulating restart of the application to see the changes, this code is for development only");
    
    // This is a simple way to "restart" the application,
    // NOTE restarting or killing the application is not allowed by apple guidelines.
    NSString *nibName = self.nibName;
    UIViewController *rootViewcontroller = (UIViewController *)([[[self class] alloc] initWithNibName:nibName bundle:nil]);
    [self  presentModalViewController:rootViewcontroller animated:YES];
}

-(IBAction)loadFromNetwork:(id)sender
{
    if (mVgMyRemoteMapManager == NULL)
    {
        // IMPORTANT:
        // The below information relates to the Visioglobe Map Manager
        // REST web service.
        // If you have your own account with the Map Manager web service,
        // then you will want to update below with your details (which will be
        // provided by Visioglobe).
        VgMyRemoteMapManagerConfig lConfig;
        std::string lMapName = "Data.Generic.sg2"; // If lMapName is empty, it will load the first map associated with the account.
        lConfig.mUsername = "sample-map-generic";
        lConfig.mPassword = "sample-map-generic";
        lConfig.mServerURL = "https://mapmanager.visioglobe.com/public/";
        lConfig.mCallback = new VgMyControllerRemoteMapManagerCallback(self,lMapName);
        
        // Maps are stored in the Documents directory
        NSArray* lDocumentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString* lMapStoratePath = [lDocumentPaths objectAtIndex:0];

        // The caches is used for the temporary directory
        NSArray* lCachesPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
        NSString* lPathTemp = [lCachesPaths objectAtIndex:0];

        
        mVgMyRemoteMapManager = new VgMyRemoteMapManager([mMapView getApplication],
                                                         lConfig,
                                                         [lMapStoratePath UTF8String],
                                                         [lPathTemp UTF8String]);
    }
    mVgMyRemoteMapManager->list();
    
}

-(IBAction) switchToGlobalView:(id)sender
{
    if (mVgMyViewControllerImpl && mVgMyViewControllerImpl->mController)
    {
        mVgMyViewControllerImpl->mController->switchToGlobalView();
    }
}
@end

./navigationModule/Src/Qt/QtVisioSample.cpp

/*
 * Copyright 2010, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 * 
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 * 
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 * 
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 * 
 * Contact information:  Visioglobe SAS, 
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

#ifdef WIN32
#include "QtVisioSample.hxx"

#include <QtGui/QMessageBox>
#include <QtGui/QGroupBox>
#include <QtGui/QGridLayout>
#include <QtGui/QMenuBar>
#include <QtGui/QIcon>
#include <QtGui/QPushButton>

#include "VgApplication/VgIApplication.h"
#include "VgApplication/VgIModule.h"
#include "VgApplication/VgIManipulatorManager.h"
#include "VgApplication/VgIModuleManager.h"

#include "VgEngine/VgIEngine.h"
#include "VgEngine/VgICamera.h"
#include "VgEngine/VgIDatabase.h"
#include "VgEngine/VgILicenseManager.h"

#include "Modules/3D/VgIGeometryCallback.h"
#include "Modules/3D/VgIGeometryEvent.h"

#include "Modules/Map/VgIMapModule.h"
#include "Modules/Map/VgPlaceDescriptor.h"
#include "Modules/Map/VgIPlaceListener.h"

#include "Modules/Navigation/VgINavigationModule.h"

#include "Qt/VgQtScene.hxx"
#include "Qt/VgQtGraphicsView.hxx"

#include "VgMyBasicApplicationController.h"
#include "VgMyFloorPoiCallback.h"
#include "VgMyStackedLayerAndCameraHandler.h"
#include "VgMyRoutingHelper.h"
#include "VgMyNavigationHelper.h"
#include "VgMyInstructionPathDisplay.h"
#include "VgMyTextureLoader.h"
#include "VgMyAvatarDisplay.h"
#include "VgMyPlaceConfigurationSetter.h"

#include "VgMyQtSimulatedPositionProvider.hxx"
//#include "VgQtModelWidget.hxx"
//#include "VgQtLightingDock.hxx"
#include "VgQtWidget.hxx"

#include "VgMyMapManagerListParser.h"

#include "VgMyZipUtils.h"
#include "VgMyRemoteMapManager.h"

#include "Qt/Moc/VgMyQtSimulatedPositionProvider.hxx"
#include "Qt/Moc/VgQtRoutingDisplayWidget.hxx"
#include "Qt/Moc/VgQtRoutingWidget.hxx"
#include "Qt/Moc/VgQtInstructionWidget.hxx"
#include "Qt/Moc/VgQtWidget.hxx"
#include "Qt/Moc/VgMyQtBubbleView.hxx"
#include "Qt/Moc/VgMyQtCentralOverlayWidget.hxx"

#include "Qt/VgMyQtPreferences.h"

VgMyStartPointPoiCallback::VgMyStartPointPoiCallback(QWidget* pParent)
: mParent(pParent)
{}

VgMyStartPointPoiCallback::~VgMyStartPointPoiCallback()
{}

void VgMyStartPointPoiCallback::handleGeometryEvent (const Vg3DModule::VgIGeometryEvent& pEvent)
{
    QMessageBox::information(mParent, "POI clicked", "The Start Point has been clicked");
}

QtVisioSample::QtVisioSample(QString& pApplicationDirPath, QWidget* parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
, mController(NULL)
, mVgQtWidget(NULL)
, mRoutingWidget(NULL)
, mModelWidget(NULL)
, mVgApplication(NULL)
, mStartPointCallback(NULL)
, mLayerAndCameraHandler(NULL)
, mRoutingHelper(NULL)
, mRoutingDisplayWidget(NULL)
, mNavigationHelper(NULL)
, mInstructionPathDisplay(NULL)
, mInstructionWidget(NULL)
, mTextureLoader(NULL)
, mAvatarDisplay(NULL)
, mAvatarOnRouteDisplay(NULL)
, mPlaceConfigSetter(NULL)
, mLocationProvider(NULL)
, mApplicationDirPath(pApplicationDirPath)
, mProgressBar(NULL)
, mLightingDock(NULL)
, mVgMyRemoteMapManager(NULL)
, mCentralOverlayWidget(NULL)
{

#ifdef WIN32
    setWindowIcon(QIcon(":/Icon.png"));
#endif // WIN32

    setupUi(this);

    mProgressBar = new QProgressBar(this);
    mProgressBar->setRange(0,100);
    verticalLayout->addWidget(mProgressBar);
    mProgressBar->setHidden(true);

    QPushButton *lButtonLoad = new QPushButton("&Load Local", this);
    verticalLayout->addWidget(lButtonLoad);
    connect(lButtonLoad,SIGNAL(clicked(  )),
        this,SLOT(onLoadLast(  )));

    QPushButton *lButton = new QPushButton("&Download", this);
    verticalLayout->addWidget(lButton);
    connect(lButton,SIGNAL(clicked(  )),
        this,SLOT(onReloadFromNetwork(  )));

    mStackButton = new QPushButton("&Toggle View Mode", this);
    verticalLayout->addWidget(mStackButton);
    connect(mStackButton,SIGNAL(clicked(  )),
        this,SLOT(onToggleViewMode(  )));

    mVgQtWidget = new VgQtWidget(this, 0);
    setCentralWidget(mVgQtWidget);
    mVgApplication = mVgQtWidget->editScene()->getApplication();
    // Configure the interaction mode here :
    mVgQtWidget->setInteractionMode(VgQtScene::eIM_firstEvent);


    const std::string lImageResourcesDirectory = pApplicationDirPath.toStdString() + "/../../../../../Common/Media/";
    mTextureLoader = new VgMyTextureLoader(mVgApplication, lImageResourcesDirectory);

    return;
}
bool QtVisioSample::verifyMap(const VgMyQtPreferences& pConfig, std::string &pErrorOut)
{
    // use a separate application for the verification
    VgQtWidget *lVgQtWidget = new VgQtWidget(this, 0);
    VgApplication::VgIApplication *lApplication = lVgQtWidget->editScene()->getApplication();

    bool lSuccess = lApplication->editEngine()->editDatabase()->loadConfiguration(pConfig.getConfigurationFile(), pConfig.getSecret(), pConfig.getLicenseURL());

    if (!lSuccess)
    {
        VgEngine::VgErrorCode lErrorCode = lApplication->editEngine()->getLastError();
        pErrorOut = lApplication->editEngine()->getErrorString(lErrorCode);
    }
    // no need to unload configuration, it will be destroyed with the "separate application"
    delete lVgQtWidget;
    return lSuccess;
}

bool QtVisioSample::loadMap(const VgMyQtPreferences& pConfig ,std::string &pErrorOut)
{
    onUnloadMap();

    mController = new VgMyBasicApplicationController(*mVgApplication, mTextureLoader);

    if ( !mController->loadConfiguration(pConfig.getConfigurationFile(), pConfig.getSecret(), pConfig.getLicenseURL(), 0) )
    {
        VgEngine::VgErrorCode lErrorCode = mVgApplication->editEngine()->getLastError();
        pErrorOut = mVgApplication->editEngine()->getErrorString(lErrorCode);
        return false;
    }

    mRoutingWidget = new VgQtRoutingWidget(mController);
    verticalLayout->addWidget(mRoutingWidget);
    mRoutingWidget->setHidden(false);

    //mModelWidget = new VgQtModelWidget(mVgApplication, this);
    //connect(mModelWidget, SIGNAL(changedFOV()), this, SLOT(refreshStackParameters()));
    //verticalLayout->addWidget(mModelWidget);
    //mModelWidget->setHidden(false);

    mLayerAndCameraHandler = new VgMyStackedLayerAndCameraHandler(mVgApplication, mController, mVgQtWidget->editScene()->sceneRect().width(), mVgQtWidget->editScene()->sceneRect().height());
    mController->setLayerAndCameraHandler(mLayerAndCameraHandler);
    configureStackedLayerAndCameraHandler();

    int lNumOfLayers = mController->getNumberOfLayers();

    mLocationProvider = new VgMyQtSimulatedPositionProvider(mVgApplication, mLayerAndCameraHandler);
    mLocationProvider->setListener(mController);

    // ADD OTHER WIDGET ON TOP OF THE MAP
    if (lNumOfLayers > 1)
    {
        // NOTE: this widget contains a .ui with all the things one could 
        // want to overlay on the screen, in this case the go to stack view button.
        mCentralOverlayWidget = new VgMyQtCentralOverlayWidget(mController);
        // Connect the QGraphicsView and the widget for automatic resizing.
        connect(mVgQtWidget->editView(), SIGNAL(onPostResizeScene(QResizeEvent*)), mCentralOverlayWidget, SLOT(resizeNeeded(QResizeEvent*)));
        // Set the initial size
        mCentralOverlayWidget->setGeometry(mVgQtWidget->editView()->geometry());
        mVgQtWidget->editScene()->addWidget(mCentralOverlayWidget);
        mController->addLayerAndCameraListener(mCentralOverlayWidget);
    }
    if (mController->hasMapModule())
    {
        VgMapModule::VgIMapModule* lMapModule = static_cast< VgMapModule::VgIMapModule* >(mVgApplication->editModuleManager()->queryModule("Map"));
        mPlaceConfigSetter = new VgMyPlaceConfigurationSetter(mTextureLoader, mVgApplication->editEngine(), mApplicationDirPath.toStdString() + "/../../../../../Common/Media/");

        // To set name and icons for places: illustrates setPlaceName and setPlaceIcon
        mPlaceConfigSetter->configurePlaces(lMapModule);

        delete mPlaceConfigSetter;
        mPlaceConfigSetter = NULL;

        // Add a listener that will be notified when a place is clicked.
        mSamplePlaceListenerWithBubble = new VgMyMapPlaceListenerWithBubble(mVgQtWidget->editScene(), mController);
        // we add mSamplePlaceListenerWithBubble as a listener to LayerAndCamera events, to
        // disable activating the bubble in global view.
        mController->addLayerAndCameraListener(mSamplePlaceListenerWithBubble.get());
    
        if (mController->hasRoutingModule())
        {
            mRoutingHelper = new VgMyRoutingHelper(mVgApplication, mTextureLoader, mController->getRouteCallback(), mLayerAndCameraHandler);
            mRoutingDisplayWidget = new VgQtRoutingDisplayWidget(mRoutingHelper);
            verticalLayout->addWidget(mRoutingDisplayWidget);
            mRoutingDisplayWidget->setHidden(true); // hide() is not used because overridden. 
            connect(mRoutingDisplayWidget, SIGNAL(onClearRoute()), this, SLOT(onClearRoute()));

            // NOTE : in this basic sample mRouteCreator and mRouteDisplayListener.
            // This has been done voluntarily too show the separation of concerns:
            // creation and display could be hanbdle in distinct entities
            mController->setRouteCreator(mRoutingHelper);
            mController->addRouteDisplay(mRoutingDisplayWidget);

            // Add a specific callback for the start point only.
            mStartPointCallback = new VgMyStartPointPoiCallback(this);
            mRoutingHelper->setPoiCallback(VgMyRoutingHelper::kStartPointStrID, mStartPointCallback);

            if (mController->hasNavigationModule())
            {
                mNavigationHelper = new VgMyNavigationHelper(static_cast<VgNavigationModule::VgINavigationModule*>(mVgApplication->editModuleManager()->queryModule("Navigation")));
                mController->setNavigationCreator(mNavigationHelper);

                // This highlights the current segment of the navigation.
                bool lShowNavigationSegmentDebug = false;
                if (lShowNavigationSegmentDebug)
                {
                    mInstructionPathDisplay = new VgMyInstructionPathDisplay(mVgApplication);
                    mController->addInstructionDisplay(mInstructionPathDisplay);
                }

                mInstructionWidget = new VgQtInstructionWidget(static_cast<VgMapModule::VgIMapModule*>(mVgApplication->editModuleManager()->queryModule("Map")), mController);
                verticalLayout->addWidget(mInstructionWidget);
                mInstructionWidget->setHidden(true);// hide() is not used because overridden. 
                mController->addInstructionDisplay(mInstructionWidget);

                // This avatar is on the "injected" gps position.
                mAvatarDisplay = new VgMyAvatarDisplay(mVgApplication, mTextureLoader, false);
                mController->addNavigationPositionDisplay(mAvatarDisplay);

                // This avatar's position is on the route, closest to the last injected gps position.
                mAvatarOnRouteDisplay = new VgMyAvatarDisplay(mVgApplication, mTextureLoader, true);
                mController->addNavigationPositionDisplay(mAvatarOnRouteDisplay);
            }
        }
        //mVgApplication->editManipulatorManager()->selectManipulator("2D");
        //mVgApplication->editManipulatorManager()->selectManipulator("simpleTrackball");

        //mLightingDock = new VgQtLightingDock(mVgApplication, this);
        //addDockWidget(Qt::RightDockWidgetArea, mLightingDock);
    }

    if (lNumOfLayers > 1)
    {
        mLayerAndCameraHandler->switchToGlobalView();
    }
    else
    {
        mLayerAndCameraHandler->switchToDetailedView();
    }

    return true;
}
void QtVisioSample::onUnloadMap()
{
    if (mVgApplication != NULL)
    {
         VgMapModule::VgIMapModule* lMapModule = static_cast< VgMapModule::VgIMapModule* >(mVgApplication->editModuleManager()->queryModule("Map"));
        if ( lMapModule != NULL )
        {
            lMapModule->removeListener(mSamplePlaceListenerWithBubble);
            mSamplePlaceListenerWithBubble = NULL;
        }
    }

    // do an "unloadConfiguration()"
    // mController needs to be deleted before any of the object it uses
    // since there is no link between them (he might try to use a deleted object)
    if (mController)
    {
        delete mController;
        mController = NULL;
    }

    delete mLocationProvider;   // in this sample, it is a QT object.
    mLocationProvider = NULL;

    delete mLayerAndCameraHandler;
    mLayerAndCameraHandler = NULL;
    delete mRoutingHelper;
    mRoutingHelper = NULL;
    delete mNavigationHelper;
    mNavigationHelper = NULL;
    
    delete mInstructionPathDisplay;
    mInstructionPathDisplay = NULL;

    delete mAvatarDisplay;
    mAvatarDisplay = NULL;
    delete mAvatarOnRouteDisplay;
    mAvatarOnRouteDisplay = NULL;

    // Widgets
    delete mRoutingWidget;
    mRoutingWidget = NULL;
    delete mModelWidget;
    mModelWidget = NULL;
    delete mRoutingDisplayWidget;
    mRoutingDisplayWidget = NULL;
    delete mInstructionWidget;
    mInstructionWidget = NULL;
    delete mCentralOverlayWidget;
    mCentralOverlayWidget = NULL;

    delete mLightingDock;
    mLightingDock = NULL;

    // mStartPointCallback is a VgRefPtr
    mStartPointCallback = NULL;
}

QtVisioSample::~QtVisioSample()
{
    onUnloadMap();

    delete mTextureLoader;
    mTextureLoader = NULL;

    delete mProgressBar;
    mProgressBar = NULL;

    delete mVgQtWidget;
    mVgQtWidget = NULL;
}

const VgMyQtPreferences& QtVisioSample::getConfigPreferences() const
{
    return mConfigPreferences;
}

VgMyQtPreferences& QtVisioSample::editConfigPreferences()
{
    return mConfigPreferences;
}

void QtVisioSample::setConfigPreferences(const VgMyQtPreferences& pConfigPreferences)
{
    mConfigPreferences = pConfigPreferences;
}



void QtVisioSample::onClearRoute()
{
    if (mRoutingDisplayWidget != NULL)
    {
        mRoutingDisplayWidget->setHidden(true);
    }

    if (mInstructionWidget != NULL)
    {
        mInstructionWidget->setHidden(true);
    }

    mController->deleteRoute();
}

void QtVisioSample::onLoadLast()
{
     std::string lErrorOut;
    if (loadMap(mConfigPreferences, lErrorOut) == false)
    {
        QMessageBox::critical(this, "Cannot load configuration", QString::fromStdString(lErrorOut));
        return;
    }
}

void QtVisioSample::onResetPreferences()
{
    // After this you need to do a download, or restart the application.
    VgMyQtPreferences::reset();

    QMessageBox::information(this, "Preferences resetted", QString("You should restart the application to see the effects"));

}

class VgMyControllerRemoteMapManagerCallback : public VgMyRemoteMapManagerCallback
{
protected:
    QtVisioSample* mVisioSample;
    VgMyMapManagerListParser::Entry mEntry;

    virtual ~VgMyControllerRemoteMapManagerCallback()
    {
    }

public:
    VgMyControllerRemoteMapManagerCallback(QtVisioSample* pVisioSample) 
        :
        mVisioSample(pVisioSample)
        {}

    virtual void listFinished(VgMyRemoteMapManager* pRemoteMapManager, ErrorCode pErrorCode, VgMyMapManagerListParser* pListParser)
    {
        // reset the entry.
        mEntry = VgMyMapManagerListParser::Entry();
        
        if (pErrorCode == eSuccess && pListParser != NULL && pListParser->isValid())
        {
            while ( ! pListParser->finished())
            {
                VgMyMapManagerListParser::Entry lEntry = pListParser->getNext();
                
                if (lEntry.mValid)
                {
                    // pick first entry if mMapName is empty
                
                    const VgMyQtPreferences& lConfig = mVisioSample->getConfigPreferences();
                    bool lUseMapName;
                    std::string lMapName;
                    unsigned int lMapID;
                    lConfig.getMapNameOrMapID(lUseMapName,lMapName,lMapID);

                    if ((lUseMapName && (lMapName.empty() || lEntry.mName.find(lMapName) != std::string::npos)) ||
                        (!lUseMapName && (lEntry.mID == lMapID)))
                    {
                        if (lEntry.mVersion != lConfig.getVersion())
                        {
                            // The versions have changed or this is the first download
                            // Show dialog box

                             QMessageBox::StandardButton reply;
                             reply = QMessageBox::question(mVisioSample, "Title",
                                                             "There is a more recent map, do you want to download it?",
                                                             QMessageBox::Yes | QMessageBox::Cancel);
                             if (reply == QMessageBox::Yes)
                             {
                                    mEntry = lEntry;
                                    mVisioSample->editConfigPreferences().setSecret(mEntry.mSecretCode);
                                    mVisioSample->editConfigPreferences().setLicenseID(mEntry.mLicenseID);

                                    mVisioSample->mProgressBar->setValue(0);
                                    mVisioSample->mProgressBar->setHidden(false);
                                    bool lStatus = pRemoteMapManager->downloadMap(mEntry.mID);
                             }
                        }
                        else
                        {
                            QMessageBox::information(mVisioSample, "Information", "No need to update you already have the latest version");
                        }
                        // we don't download map, and we do not give an error.
                        return;

                    }
                }
            }
        }
        
        if (pErrorCode == eSuccess)
        {
            QMessageBox::critical(mVisioSample, "Download Failed", "Download List succeded, but your map was not found");
        }
        else
        {
            QMessageBox::critical(mVisioSample,"Download Failed", "Download list failed, check internet connection?");
        }
    }
    
    virtual void mapDownloadProgress(VgMyRemoteMapManager* pRemoteMapManager, int pBytesReceived,int pBytesTotal)
    {
        mVisioSample->downloadProgress(pBytesReceived, pBytesTotal);
    }

    virtual void mapDownloadFinished(VgMyRemoteMapManager* pRemoteMapManager, ErrorCode pErrorCode, unsigned int pMapID)
    {
        mVisioSample->mProgressBar->setHidden(true);

        if (pErrorCode == eSuccess)
        {
            std::string lConfigurationPath;
            if (pRemoteMapManager->getLocalConfigPathForMap(pMapID, lConfigurationPath))
            {
                // we make a copy of the preferences, only if the verify works, we replace them.
                VgMyQtPreferences lPreferences = mVisioSample->getConfigPreferences();
                
                lPreferences.setConfigurationFile(lConfigurationPath);
                lPreferences.setSecret(mEntry.mSecretCode);
                lPreferences.setLicenseID(mEntry.mLicenseID);
                lPreferences.setVersion(mEntry.mVersion);

                std::string lErrorStr;
                if (mVisioSample->verifyMap(lPreferences,lErrorStr))
                {
                    lPreferences.save();
                    mVisioSample->setConfigPreferences(lPreferences);
                    mVisioSample->loadMap(lPreferences,lErrorStr);
                }
                else
                {
                    QMessageBox::critical(mVisioSample, "Downloaded Map is not valid", QString::fromStdString(lErrorStr));
                }
                return;
            }
        }
        QMessageBox::critical(mVisioSample, "Download Failed", "Download map failed (list succedeed)");
    }
};

void QtVisioSample::downloadProgress(int pBytesReceived, int pBytesTotal)
{
    // normally update progress bar.
    if (pBytesTotal > 0)
    {
        int lProgress = pBytesReceived*100/pBytesTotal;
        mProgressBar->setValue(lProgress);
    }
    else
    {
        mProgressBar->setValue(0);
    }
}

void QtVisioSample::onReloadFromNetwork()
{
    if (mVgMyRemoteMapManager == NULL)
    {
        VgMyRemoteMapManagerConfig lConfig;
        lConfig.mUsername = getConfigPreferences().getUsername();
        lConfig.mPassword = getConfigPreferences().getPassword();
        lConfig.mServerURL = getConfigPreferences().getServerURL();
        lConfig.mCallback = new VgMyControllerRemoteMapManagerCallback(this);
        
        mVgMyRemoteMapManager = new VgMyRemoteMapManager(mVgApplication,lConfig,mApplicationDirPath.toStdString(),mApplicationDirPath.toStdString());
    }

    mVgMyRemoteMapManager->list();
}

void QtVisioSample::onToggleInjectPosition(bool pValue)
{
    if (mLocationProvider == NULL)
    {
        return;
    }

    if (pValue)
    {
        mLocationProvider->enable();
    }
    else 
    {
        mLocationProvider->disable();
        mController->clearNavigationPositionDisplays();
    }
}

void QtVisioSample::onToggleViewMode()
{
    if (mController == NULL)
    {
        return;
    }

    if (mController->isGlobalView())
    {
        mController->switchToDetailedView();
    }
    else
    {
        mController->switchToGlobalView();
    }
}

// Configure VgMyStackedLayerAndCameraHandler parameters
// For a list of what paramters are configurable, please see
// VgMyStackedLayerAndCameraHandler
void QtVisioSample::configureStackedLayerAndCameraHandler()
{
    // IMPORTANT
    // These parameters are chosen specifically for the Visioglobe Map Generic sample
    // If developing with a different map bundle then there are two choices:
    // 1/ comment the below configurations.  VgMyStackedLayerAndCameraHandler will
    // automatically calculate values which 'should' work for the map bundle.
    // 2/ change the configurations below to work with the map bundle.

    mLayerAndCameraHandler->setParam(VgMyStackedLayerAndCameraHandler::eLayerMaxSize, 800);
    mLayerAndCameraHandler->setParam(VgMyStackedLayerAndCameraHandler::eLayerDistance, 30);
    mLayerAndCameraHandler->setParam(VgMyStackedLayerAndCameraHandler::eLayerDistanceFromCurrent, 170);
    
    // Force the stack view to update
    mLayerAndCameraHandler->refreshStackView();
}

VgMyLayerAndCameraHandler* QtVisioSample::editLayerAndCameraHandler()
{
    return mLayerAndCameraHandler;
}

void QtVisioSample::on_actionAbout_triggered()
{
    QMessageBox::about(this, "About VisioDevKit Sample", QString::fromStdString("Using VisioDevKit " + mVgApplication->editEngine()->editLicenseManager()->getVersion()));
}

void QtVisioSample::disableUI()
{
    menubar->hide();
    mContextDockWidget->hide();
    statusbar->hide();

    setWindowFlags(Qt::FramelessWindowHint);
}

void QtVisioSample::displayRoute(const std::string& pStartID, const std::string& pEndID)
{
    if (mController != NULL && mVgApplication != NULL)
    {
        VgMapModule::VgIMapModule* lMapModule = static_cast< VgMapModule::VgIMapModule* >(mVgApplication->editModuleManager()->queryModule("Map"));

        if (lMapModule != NULL)
        {
            mController->deleteRoute();

            VgMapModule::VgPlaceDescriptor lPlaceDescriptor;
            std::string lLayerName;
            bool lStartAndEndOnSameLayer = false;
            if (lMapModule->queryPlaceDescriptor(pStartID, lPlaceDescriptor))
            {
                lLayerName = lPlaceDescriptor.mLayerName;
            }

            lStartAndEndOnSameLayer = lMapModule->queryPlaceDescriptor(pEndID, lPlaceDescriptor) && (lLayerName == lPlaceDescriptor.mLayerName);

            mController->setRoutePoint(VgMyRouteCreator::eStart, pStartID);
            mController->setRoutePoint(VgMyRouteCreator::eEnd, pEndID);

            if (lStartAndEndOnSameLayer)
            {
                if (mController->getFocusedLayerName() != lLayerName)
                {
                    mController->gotoLayer(lLayerName);
                }

                if (mController->isGlobalView())
                {
                    mController->switchToDetailedView(true);
                }
            }
            else
            {
                if (!mController->isGlobalView())
                {
                    mController->switchToGlobalView();
                }
            }
        }
    }
}

void QtVisioSample::onReloadShaders()
{
    mVgApplication->editEngine()->reloadShaders();
}

void QtVisioSample::refreshStackParameters ()
{
    if (mLayerAndCameraHandler)
    {
        mLayerAndCameraHandler->refreshParameters(mVgQtWidget->size().width(), mVgQtWidget->size().height());
    }
}

#endif

./navigationModule/Src/Qt/main.cpp

/*
 * Copyright 2010, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */
#include <QtGui/QApplication>
#include <QtGui/QFileDialog>
#include "QtVisioSample.hxx"

#include "VgApplication/VgIApplication.h"
#include "VgEngine/VgIEngine.h"
#include "VgEngine/VgILicenseManager.h"
#include "Qt/VgMyQtPreferences.h"

#if defined DEBUG && defined WIN32
#define WIN32_TRACK_ALLOCS
#endif

#ifdef WIN32_TRACK_ALLOCS

#include <crtdbg.h>

_CRT_ALLOC_HOOK msOldAlloc = NULL;
int vgAllocHook (int allocType, void* userData, size_t size, int blockType, long requestNumber, const unsigned char* filename, int lineNumber)
{
    return msOldAlloc(allocType, userData, size, blockType, requestNumber, filename, lineNumber);
}

//#define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ )
//#define new DEBUG_NEW

#endif // WIN32_TRACK_ALLOCS


void usage()
{
    printf("\n");
    printf("QtVisioSample\n");
    printf("\n");
    printf(" Usage:  [--doNotLoadAtStart] --configurationFile path_vg_config.xml\n"
           "         --secret pSecret\n"
           "         --licenseID pLicenseID\n"
           "         --licenseBaseURL pLicenseBaseURL\n");
    printf(" or\n");
    printf(" Usage:  [--downloadMap] --username pUsername --password pPassword\n"
           "         [--mapName mapname|--mapID mapNumber] [--serverURL pServerURL]\n");
    printf("\n");
    printf("         [--resetPreferences]\n");
    printf("         [--savePreferences]\n");
    printf("         [--printSavedPreferences]\n");

    printf("\n");
    printf("         [--routeStart ID]\n");
    printf("         [--routeEnd ID]\n");
    printf("         [--noUI]\n");
    printf("         [--windowRect pX pY width height]\n");

    printf("         Note: --downloadMap:  will start by downloading a map right away\n");
    printf("\n");
    printf(" Compiled: %s %s\n",__DATE__,__TIME__);

    VgApplication::VgIApplication *lApp = VgApplication::VgIApplication::createApplication();
    std::string lEngineVersion =  lApp->editEngine()->editLicenseManager()->getVersion();
    printf(" SDK Version: %s\n",lEngineVersion.c_str());
    delete lApp;
    exit(-1);
}

int main (int argc, char** argv)
{
#ifdef WIN32_TRACK_ALLOCS
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
    msOldAlloc = _CrtSetAllocHook(vgAllocHook);
#endif // WIN32_TRACK_ALLOCS

    int lResult = 0;
    
    QApplication a(argc, argv);

    // Used by QSettings
    QCoreApplication::setOrganizationName("Visioglobe");
    QCoreApplication::setOrganizationDomain("visioglobe.com");
    QCoreApplication::setApplicationName("QtVisioSample");

        QtVisioSample lVisioSample(a.applicationDirPath(), 0/*, Qt::FramelessWindowHint*/);

    bool lOverridePreferences = false;
    VgMyQtPreferences lPreferences;

    /* Setup default prefences */
    lPreferences.setConfigurationFile(a.applicationDirPath().toStdString() + "/../../../../../Data/PVRTC/vg_config.xml");
    lPreferences.setSecret(0);
    lPreferences.setVersion("no version");

    lPreferences.setLicenseBaseURL("http://license.visioglobe.com/renew/");
    lPreferences.setLicenseID("licenseID_here");

    lPreferences.setServerURL("https://mapmanager.visioglobe.com/public/");

    lPreferences.setUsername("sample-map-generic");
    lPreferences.setPassword("sample-map-generic");
    lPreferences.setMapNameOrMapID(true,"Data.Generic.sg2",0);

    // don't forget to set the preferences as valid.
    lPreferences.setValid();
    // use "hard coded" preferences if nothing else.
    lVisioSample.setConfigPreferences(lPreferences);

    //lVisioSample.showFullScreen();

    char* lConfigFile = NULL;
    char* lLicenseID = NULL;
    char* lLicenseBaseURL = NULL;
    char* lUsername = NULL;
    char* lPassword = NULL;
    char* lMapName = NULL;
    unsigned int lMapID = 0;
    char* lServerURL = NULL;

    bool lDownloadMapAtStart = false;
    bool lShouldResetPreferences = false;
    bool lShouldSavePreferences = false;
    bool lShouldPrintSavedPreferences = false;
    bool lLoadAtStart = true;

    std::string lRouteStart;
    std::string lRouteEnd;

    unsigned int lSecret = 0;
    bool lIsSecretSet = false;
    // options 
    int argIndex = 1; // skip program name
    while (argIndex < argc)
    {
        //  --configurationFile path_vg_config.xml --secret pSecret --licenseID pLicenseID

        if (strcmp(argv[argIndex],"--configurationFile") == 0)
        {
            argIndex++;
            if (argIndex == argc) usage();
            lConfigFile = argv[argIndex];
            lOverridePreferences = true;
            lPreferences.setConfigurationFile(lConfigFile);
        }
        else if (strcmp(argv[argIndex],"--secret") == 0)
        {
            argIndex++;
            if (argIndex == argc) usage();
            lSecret = atoi(argv[argIndex]);
            lIsSecretSet = true;
            lOverridePreferences = true;
            lPreferences.setSecret(lSecret);
        }
        else if (strcmp(argv[argIndex],"--licenseID") == 0)
        {
            argIndex++;
            if (argIndex == argc) usage();
            lLicenseID = argv[argIndex];
            lOverridePreferences = true;
            lPreferences.setLicenseID(lLicenseID);
        }
        else if (strcmp(argv[argIndex],"--licenseBaseURL") == 0)
        {
            argIndex++;
            if (argIndex == argc) usage();
            lLicenseBaseURL = argv[argIndex];
            lOverridePreferences = true;
            lPreferences.setLicenseBaseURL(lLicenseBaseURL);
        }

        //  [--downloadMap] --username pUsername --password pPassword [--mapName mapname] [--serverURL pServerURL]
        else if (strcmp(argv[argIndex],"--username") == 0)
        {
            argIndex++;
            if (argIndex == argc) usage();
            lUsername = argv[argIndex];
            lOverridePreferences = true;
            lPreferences.setUsername(lUsername);
        }
        else if (strcmp(argv[argIndex],"--password") == 0)
        {
            argIndex++;
            if (argIndex == argc) usage();
            lPassword = argv[argIndex];
            lOverridePreferences = true;
            lPreferences.setPassword(lPassword);
        }
        else if (strcmp(argv[argIndex],"--mapName") == 0)
        {
            argIndex++;
            if (argIndex == argc) usage();
            lMapName = argv[argIndex];
            lOverridePreferences = true;
            lPreferences.setMapNameOrMapID(true,lMapName,0);
        }
        else if (strcmp(argv[argIndex],"--mapID") == 0)
        {
            argIndex++;
            if (argIndex == argc) usage();
            lMapID = atoi(argv[argIndex]);
            lOverridePreferences = true;
            lPreferences.setMapNameOrMapID(false,std::string(),lMapID);
        }
        else if (strcmp(argv[argIndex],"--serverURL") == 0)
        {
            argIndex++;
            if (argIndex == argc) usage();
            lServerURL = argv[argIndex];
            lOverridePreferences = true;
            lPreferences.setServerURL(lServerURL);
        }
        else if (strcmp(argv[argIndex],"--downloadMap") == 0)
        {
            lDownloadMapAtStart = true;
        }
        else if (strcmp(argv[argIndex],"--doNotLoadAtStart") == 0)
        {
            lLoadAtStart = false;
        }
        else if (strcmp(argv[argIndex],"--resetPreferences") == 0)
        {
            lShouldResetPreferences = true;
        }
        else if (strcmp(argv[argIndex],"--printSavedPreferences") == 0)
        {
            lShouldPrintSavedPreferences = true;
        }
        else if (strcmp(argv[argIndex],"--save") == 0)
        {
            // save the preferences
            lShouldSavePreferences = true;
        }
        else if (strcmp(argv[argIndex],"--routeStart") == 0)
        {
            argIndex++;
            if (argIndex == argc) usage();
            lRouteStart = argv[argIndex];
        }
        else if (strcmp(argv[argIndex],"--routeEnd") == 0)
        {
            argIndex++;
            if (argIndex == argc) usage();
            lRouteEnd = argv[argIndex];
        }
        else if (strcmp(argv[argIndex],"--windowRect") == 0)
        {
            argIndex++;
            if (argIndex == argc) usage();
            int lX = atoi(argv[argIndex]);

            argIndex++;
            if (argIndex == argc) usage();
            int lY = atoi(argv[argIndex]);

            argIndex++;
            if (argIndex == argc) usage();
            int lWidth = atoi(argv[argIndex]);

            argIndex++;
            if (argIndex == argc) usage();
            int lHeight = atoi(argv[argIndex]);

            lVisioSample.setGeometry(lX, lY, lWidth, lHeight);
        }
        else if (strcmp(argv[argIndex],"--noUI") == 0)
        {
            lVisioSample.disableUI();
        }
        else
        {
            usage();
        }
        argIndex++;
    }

    if (lShouldResetPreferences)
    {
        // reset any saved preferences
        VgMyQtPreferences::reset();
    }

    if (lShouldSavePreferences)
    {
        lPreferences.save();
    }

    // setup preferences, either new ones by hand, or from saved preferences
    // otherwise, hardcoded ones setup above.
    VgMyQtPreferences lLastSavedPreferences = VgMyQtPreferences::getFromPreferences();

    if (lShouldPrintSavedPreferences)
    {

        if (lLastSavedPreferences.isValid())
        {
            lLastSavedPreferences.print();
        }
        else
        {
            printf("There are no saved (valid) preferences\n");
        }
    }

    if (lOverridePreferences)
    {
        lVisioSample.setConfigPreferences(lPreferences);
    }
    else if (lLastSavedPreferences.isValid())
    {
        lVisioSample.setConfigPreferences(lLastSavedPreferences);
    }

    // load last map.
    if (lDownloadMapAtStart)
    {
        lVisioSample.onReloadFromNetwork();
    }
    else if (lLoadAtStart)
    {
        lVisioSample.onLoadLast();
    }

    lVisioSample.show();

    if (lRouteStart != "" && lRouteEnd != "")
    {
        lVisioSample.displayRoute(lRouteStart, lRouteEnd);
    }

    lResult = a.exec();

    return lResult;
}

./Common/Inc/Apple/VgMyBubbleView.h

/*
 * Copyright 2011, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

#include "VgEngine/VgRefPtr.h"

#include "VgEngine/VgIEngine.h"
#include "VgEngine/VgPosition.h"

class ViewRepositionPostDrawCallback : public VgEngine::VgIEnginePostDrawCallback
{
protected:
    UIView* mView;                      
    VgEngine::VgICamera* mCamera;       
    VgEngine::VgPosition mPosition;     
    
public:
    ViewRepositionPostDrawCallback(UIView* pView, VgEngine::VgICamera* pCamera, const VgEngine::VgPosition& pPosition);
    
    virtual void postDraw (VgEngine::VgIEngineContext* pContext);
};

class VgMyRouteCreator;

@interface VgMyBubbleView : UIView 
{
    VgEngine::VgIEngine* mEngine;
    
    VgEngine::VgRefPtr<ViewRepositionPostDrawCallback> mCallback;

    UILabel* mLabelBack;
    UILabel* mLabelFront;
    UIButton* mRouteStartButton;
    UIButton* mRouteEndButton;
    
    UIButton* mButtonLeft;
    UIButton* mButtonRight;
    
    // Various views loaded from nib files
    UIWebView* mInfoWebView;
    UIView* mBubbleViewFront;
    UIView* mBubbleViewBack;
    UIView* mBubbleViewContainer;
    
    NSString* mPlaceID;
    
    VgMyRouteCreator* mRouteCreator;
};

@property (retain) IBOutlet UILabel* mLabelBack;
@property (retain) IBOutlet UILabel* mLabelFront;

@property (retain) NSString* mPlaceID;

@property (retain) IBOutlet UIButton* mRouteStartButton;
@property (retain) IBOutlet UIButton* mRouteEndButton;

@property (retain) IBOutlet UIButton* mButtonLeft;
@property (retain) IBOutlet UIButton* mButtonRight;

// Various views loaded from nib files
@property (retain) IBOutlet UIWebView* mInfoWebView;
@property (retain) IBOutlet UIView* mBubbleViewFront;
@property (retain) IBOutlet UIView* mBubbleViewBack;
@property (retain) IBOutlet UIView* mBubbleViewContainer;

-(id) initWithEngine:(VgEngine::VgIEngine*)pEngine 
            position:(const VgEngine::VgPosition &) pPosition 
              withID:(const std::string &)pID
         withRouting:(BOOL) pIsRoutingEnabled
    withRouteCreator:(VgMyRouteCreator*)pRouteCreator;

-(IBAction)closeFrame:(UIButton*)sender;
-(IBAction)toggleFrontAndBackViews:(UIButton*)sender;


-(IBAction)setRouteStart;

-(IBAction)setRouteEnd;

-(void)loadInfoView;

@end

./Common/Inc/Apple/VgMyFloorSliderView.h

/*
 * Copyright 2011, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */
 
 /*
 * VgMyFloorSliderView 
 * A view which customizes the UISlider control (note: does not subclass) in 
 * provide a more relevant user experience for changing floors.
 *
 * The number of the current floor will appear on the slider thumb and will be
 * automatically updated when a new floor is selected.
 *
 * Note: This version of the slider relies on the following resources
 * - VgMyFloorSliderView-iPad.xib (works for both iPad and iPhone)
 * - SliderTrack~ipad.png
 * - SliderTrackClear~ipad.png
 * - SliderThumb~ipad.png 
 * - SliderThumbClear.png
 * - SliderTrack.png
 * - SliderThumb.png
 */

#import <UIKit/UIKit.h>
#include "VgMyLayerAndCameraHandler.h"

@class VgMyViewController;

@protocol VgMyFloorSliderViewDelegate;

@interface VgMyFloorSliderView : UIView 
{
    VgMyLayerAndCameraHandler*  delegate;
    IBOutlet UISlider* floorSlider;
    NSInteger currentFloorIndex;
    NSInteger numberOfFloors;
    UILabel* floorLabel;
    UIImageView* floorThumbImage;
    NSMutableArray* labelCentersHeights; // array of NSNumber
    NSInteger labelFontSize;
}

@property(nonatomic,retain) IBOutlet UISlider* floorSlider;
@property(nonatomic,retain) UILabel* floorLabel;
@property(nonatomic,retain) UIImageView* floorThumbImage;
@property(nonatomic,retain) NSMutableArray* labelCentersHeights;

/*
 * currentFloorIndex represents the current floor <0...N>
 * This will need to be set manual if the floor is changed via a mechanism other 
 * then the floor slider.
 */
@property(nonatomic,assign) NSInteger currentFloorIndex;

/*
 * numberOfFloors the number of floors to be indicated by the floor slider.
 * It should be greater than 1.
 */
@property(nonatomic,assign) NSInteger numberOfFloors;

/*
 * font size of floor labels
 */
@property(nonatomic,readonly) NSInteger labelFontSize;

/*
 * Initialize the floor slider view.
 * 
 * frame - Pass in the frame of the parent view.  The slider will be automatically 
 * sized in order to correspond with it's parent view.
 * pFloorSliderViewDelegate - The delegate to handle floor slider view events.
 */
- (id)initWithFrame:(CGRect)frame
        andLayerCameraHandler:(VgMyLayerAndCameraHandler*)pFloorSliderViewDelegate;

/*
 * Used to make labels auto shrink, useful if floor names have more than 2 characters
 */
-(void)enableAutoShrinkFactor:(BOOL)pFlag withScale:(double)pScale;

-(IBAction)sliderValueChanged:(id)sender;
-(IBAction)sliderTouchUp:(id)sender;

@end


@protocol VgMyFloorSliderViewDelegate <NSObject>

@optional
/*
 * The floorSliderDidChange will be notified when the user has selected a different
 * floor to the current floor. 
 * 
 * pNewFloor - Represents the new floor and corresponds to the dataset index with
 * which that floor can be loaded.
 */
-(void) floorSliderDidChange:(unsigned int)pNewFloor;

@end

./Common/Inc/Apple/VgMyInstructionView.h

/*
 * Copyright 2011, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

#import <UIKit/UIKit.h>
#include "Modules/Navigation/VgINavigationInstruction.h"
#include "Modules/Navigation/VgINavigation.h"

#include "VgMyInstructionDisplay.h"
#include "Modules/Map/VgIMapModule.h"
#include "VgEngine/VgRefPtr.h"


// These values should match the actual view size as given by the nib file
#define HEIGHT_INSTRUCTION_VIEW     85
// Tag for instruction view
//#define INSTRUCTION_VIEW_TAG_ID     99

namespace VgApplication
{
    class VgIApplication;
};

namespace VgNavigationModule {
    class VgINavigation;
};

class VgMyInstructionUpdateListener;

@interface VgMyInstructionView : UIView
{
    BOOL mIsIPad;
    IBOutlet UILabel* mInstructionLabel;        
    IBOutlet UILabel* mInstructionLabelDetail;  
    
    IBOutlet UILabel* mDistance;
    IBOutlet UILabel* mXofYLabel;
    IBOutlet UIView* mInstructionView;
    IBOutlet UIImageView* mInstructionManeuverType;
    IBOutlet UIButton* mNextInstruction;
    IBOutlet UIButton* mPrevInstruction;
    
    // The key to accessing the interface of the VisioDevKit
    VgApplication::VgIApplication* mVgApplication;
    
    VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigationInstruction > mInstruction;
    VgMyInstructionUpdateListener* mUpdateListener;
    VgMapModule::VgIMapModule* mMapModule;
    
    int mCurrentLocaleTranslateID; // language id used by VgMyNavigationHelper::translateInstruction
}

@property(retain) UILabel* mInstructionLabel;
@property(retain) UILabel* mInstructionLabelDetail;
@property(retain) UILabel* mDistance;
@property(retain) UILabel* mXofYLabel;
@property(retain) UIView* mInstructionView;
@property(retain) UIImageView* mInstructionManeuverType;
@property(retain) UIButton* mNextInstruction;
@property(retain) UIButton* mPrevInstruction;


-(IBAction)nextInstruction:(id)sender;
-(IBAction)prevInstruction:(id)sender;
// optional
-(IBAction)clearRoute:(id)sender;

-(void)updateManeuverWithType:(unsigned int)maneuverType;

// Part of VgINavigationListenerProtocol
// NOT USED
-(void) notifyPositionUpdated: (VgEngine::VgConstRefPtr<  VgNavigationModule::VgINavigation >const&)pNavigation withPosition:(const VgEngine::VgPosition&) pPosition withTime:(double) pTime;

// NOT USED
-(void) notifyNewInstruction: (VgEngine::VgConstRefPtr<  VgNavigationModule::VgINavigation >const&)pNavigation withIndex:(unsigned int) pIndex;

-(id) initWithFrame:(CGRect)frame withApplication:(VgApplication::VgIApplication*)pVgApplication withUpdateListener:(VgMyInstructionUpdateListener *)pUpdateListener;

-(void) setInstruction:(VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigationInstruction > &) pNavigationInstruction withNavigation:(VgEngine::VgConstRefPtr<  VgNavigationModule::VgINavigation >const&)pNavigation;

@end

./Common/Inc/Apple/VgMyMapPlaceListenerWithBubble.h

/*
 * Copyright 2011, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

#include "VgIPlaceListenerWithBubble.h"
#include "VgMyLayerAndCameraListener.h"

@class VgEAGLView;

namespace VgApplication
{
    class VgIApplication;
}
namespace VgEngine
{
    struct VgPosition;
}
namespace VgMapModule {
    class VgIMapModule;
}

class VgMyLayerAndCameraHandler;
class VgMyRouteCreator;

class VgMyMapPlaceListenerWithBubble : public VgIPlaceListenerWithBubble, public VgMyLayerAndCameraListener
{
public:
    VgMyMapPlaceListenerWithBubble(VgEAGLView* pVgEAGLView, VgMyRouteCreator* pController);

    virtual ~VgMyMapPlaceListenerWithBubble();

    virtual void notifyPlaceSelected (VgApplication::VgIApplication& pVgApplication, const std::string& pID, const VgEngine::VgPosition& pPosition);

    virtual void hideBubble ();

    virtual void showBubble (const VgEngine::VgPosition& pPosition, const std::string& pID, const std::string& pMessage);
    
#pragma mark Implementation of VgMyLayerAndCameraListener
    /*
     * Implementation of interface : VgMyLayerAndCameraListener 
     */
    void layerWillChangeFrom(VgMyLayerAndCameraHandler* pSender, const std::string& pFloorFrom, const std::string& pFloorTo);
    void layerChangedTo(VgMyLayerAndCameraHandler* pSender, const std::string& pFloorFrom, const std::string& pFloorTo);
    void viewWillChange(VgMyLayerAndCameraHandler* pSender, const bool pDoesChangeFromGlobalToDetailed);
    void viewDidChange(VgMyLayerAndCameraHandler* pSender, const bool pDoesChangeFromGlobalToDetailed);
#pragma mark --

protected:
    VgEAGLView* mVgEAGLView;
    VgMapModule::VgIMapModule* mMapModule;

    VgMyRouteCreator* mRouteCreator;
    UIView* mCurrentCallout;
    std::string mCurrentAnchoredLayer;
};

./Common/Inc/Interfaces/VgMyAnchoredDisplay.h

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */
#ifndef _VGMYANCHOREDDISPLAY_H_
#define _VGMYANCHOREDDISPLAY_H_

#include "VgMyDisplayable.h"
#include <string>

class VgMyAnchoredDisplay : public VgMyDisplayable
{
public:
    virtual void setAnchorPosition(const std::string& pPlaceID) = 0;
};

#endif // _VGMYANCHOREDDISPLAY_H_

./Common/Inc/Interfaces/VgMyDisplayable.h

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

#ifndef _VGMYDISPLAYABLE_H_
#define _VGMYDISPLAYABLE_H_

class VgMyDisplayable
{
public:
    virtual void show() = 0;

    virtual void hide() = 0;

    virtual bool isVisible() = 0;
};

#endif // _VGMYDISPLAYABLE_H_

./Common/Inc/Interfaces/VgMyInstructionDisplay.h

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */
#ifndef _VGMYINSTRUCTIONDISPLAY_H_
#define _VGMYINSTRUCTIONDISPLAY_H_

#include "VgMyDisplayable.h"

#include "VgEngine/VgRefPtr.h"

namespace VgNavigationModule
{
    class VgINavigation;
};

class VgMyInstructionDisplay : public VgMyDisplayable
{
public:
    virtual void updateWithInstruction(VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigation > const& pNavigation, unsigned int pIndex) = 0;

    virtual void clear() = 0;

    virtual void show() = 0;
    virtual void hide() = 0;
    virtual bool isVisible() = 0;
};

#endif // _VGMYINSTRUCTIONDISPLAY_H_

./Common/Inc/Interfaces/VgMyInstructionUpdateListener.h

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */
#ifndef _VGMYINSTRUCTIONUPDATELISTENER_H_
#define _VGMYINSTRUCTIONUPDATELISTENER_H_

class VgMyInstructionUpdateListener
{
public:

    virtual void goToInstruction(const unsigned int pInstructionIndex) = 0;
};

#endif // _VGMYINSTRUCTIONUPDATELISTENER_H_

./Common/Inc/Interfaces/VgMyLayerAndCameraHandler.h

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */
#ifndef _VGMYLAYERANDCAMERAHANDLER_H_
#define _VGMYLAYERANDCAMERAHANDLER_H_

#include "VgEngine/VgICamera.h"
#include <string>

class VgMyLayerAndCameraHandler
{  
public:
    virtual bool isGlobalView() = 0;

    virtual void switchToGlobalView(bool pIsAnimated = true) = 0;

    virtual void switchToDetailedView(bool pIsAnimated = true) = 0;

    virtual const std::string& getFocusedLayerName() = 0;

    virtual void gotoLayer(const std::string& pLayerName, bool pIsAnimated = true) = 0;
    
    virtual void gotoLayer(const unsigned int pLayerIndex, bool pIsAnimated = true) = 0;
    
    virtual unsigned int getNumberOfLayers() = 0;

    virtual bool getLayerName(const unsigned int pLayerIndex, std::string& pLayerNameOut) = 0;
        
    virtual void gotoViewpoint(const VgEngine::VgIViewPoint& pViewPoint, const std::string& pLayerName, bool pIsAnimated = true) = 0;
    
    virtual void gotoLookAtPosition(const VgEngine::VgPosition& pPosition, const std::string& pLayerName, bool pIsAnimated = true) = 0;

    virtual void refreshParameters(unsigned int pWidth, unsigned int pHeight) = 0;
};

#endif // _VGMYLAYERANDCAMERAHANDLER_H_

./Common/Inc/Interfaces/VgMyLayerAndCameraListener.h

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */
#ifndef _VGMYLAYERUPDATELISTENER_H_
#define _VGMYLAYERUPDATELISTENER_H_

#include <string>
class VgMyLayerAndCameraHandler;

class VgMyLayerAndCameraListener
{
public:
    virtual void layerWillChangeFrom(VgMyLayerAndCameraHandler* pSender, const std::string& pFloorFrom, const std::string& pFloorTo) = 0;
    
    virtual void layerChangedTo(VgMyLayerAndCameraHandler* pSender, const std::string& pFloorFrom, const std::string& pFloorTo) = 0;
    
    virtual void viewWillChange(VgMyLayerAndCameraHandler* pSender, const bool pDoesChangeFromGlobalToDetailed) = 0;
    
    virtual void viewDidChange(VgMyLayerAndCameraHandler* pSender, const bool pDoesChangeFromGlobalToDetailed) = 0;
};

#endif // _VGMYLAYERUPDATELISTENER_H_

./Common/Inc/Interfaces/VgMyNavigationCreator.h

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */
#ifndef _VGMYNAVIGATIONCREATOR_H_
#define _VGMYNAVIGATIONCREATOR_H_

namespace VgNavigationModule
{
    struct VgINavigationRequestParameters;
};

class VgMyNavigationCreator
{
public:
    virtual void createNavigation(VgNavigationModule::VgINavigationRequestParameters& pParameters) = 0;
};

#endif // _VGMYNAVIGATIONCREATOR_H_

./Common/Inc/Interfaces/VgMyNavigationPositionDisplay.h

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */
#ifndef _VGMYNAVIGATIONPOSITIONDISPLAY_H_
#define _VGMYNAVIGATIONPOSITIONDISPLAY_H_

#include "VgMyDisplayable.h"

namespace VgEngine
{
    struct VgPosition;
};

namespace VgNavigationModule
{
    class VgINavigation;
}

class VgMyNavigationPositionDisplay : public VgMyDisplayable
{
public:

    virtual void updateWithPosition(VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigation > const& pNavigation, const VgEngine::VgPosition& pPosition) = 0;
    
    virtual void clear() = 0;

    virtual void show() = 0;
    virtual void hide() = 0;
    virtual bool isVisible() = 0;
};

#endif // _VGMYNAVIGATIONPOSITIONDISPLAY_H_

./Common/Inc/Interfaces/VgMyPoiConfigurationSetter.h

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */
#ifndef _VGMYPOICONFIGURATIONSETTER_H_
#define _VGMYPOICONFIGURATIONSETTER_H_

#include "VgEngine/VgRefPtr.h"

namespace Vg3DModule
{
    class VgIGeometryCallback;
};

#include <string>

class VgMyPoiConfigurationSetter
{
public:
    virtual void setPoiCallback(const std::string& pIdentifier, VgEngine::VgRefPtr< Vg3DModule::VgIGeometryCallback >const& pCallback) = 0;
};

#endif // _VGMYPOICONFIGURATIONSETTER_H_

./Common/Inc/Interfaces/VgMyRouteCreator.h

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */
#ifndef _VGMYROUTECREATOR_H_
#define _VGMYROUTECREATOR_H_

#include "VgMyRouteStyler.h"

#include "Modules/Routing/VgIRoutingSolver.h"
#include "VgEngine/VgAnimation.h"

#include <string>

class VgMyRouteCreator
{
public:

    enum RoutePoint {
        eStart,
        eEnd
    };
    
    virtual bool setRoutePoint(RoutePoint pPoint, const std::string& pPlaceID) = 0;
    
    
    virtual bool setRoutePoint(RoutePoint pPoint, const VgEngine::VgPosition& pPosition) = 0;
    
    virtual void resetRoutePoint(RoutePoint pPoint) = 0;

    virtual bool isRoutePointSet(RoutePoint pPoint) = 0;
    
    virtual void computeRoute() = 0;
    
    virtual VgRoutingModule::VgIRouteRequestParameters* editRoutingRequestParameters() = 0;
    
    virtual void resetRoutingRequestParameters() = 0;

    virtual VgEngine::VgRefPtr< VgEngine::VgAnimationDescriptor > getRoutePointHighlightAnimationDescriptor () = 0;

    virtual void setAvoidStairs (bool pDisabledFriendly) = 0;

    /*
     * Change the routing style of lines generated by the routing helper.
     * @param pRouteStyle route style
     * @param pRecomputeRoute
     */
    virtual void setRouteStyle (VgMyRouteStyler::RouteStyle pRouteStyle, bool pRecomputeRoute = true) = 0;
    
    /*
     * get the current route style
     * @return current route style.
     */
    virtual VgMyRouteStyler::RouteStyle getRouteStyle() const = 0;

};

#endif // _VGMYROUTECREATOR_H_

./Common/Inc/Interfaces/VgMyRouteDisplay.h

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */
#ifndef _VGMYROUTEDISPLAY_H_
#define _VGMYROUTEDISPLAY_H_

#include "VgMyDisplayable.h"
#include "VgEngine/VgRefPtr.h"

namespace VgRoutingModule
{
    class VgIRoute;
};

class VgMyRouteDisplay : public VgMyDisplayable
{
public:

    virtual bool createRouteObjects(VgEngine::VgConstRefPtr< VgRoutingModule::VgIRoute > const& pRoute) = 0;
    
    virtual void clear() = 0;

    virtual void show() = 0;
    virtual void hide() = 0;
    virtual bool isVisible() = 0;
};

#endif // _VGMYROUTEDISPLAY_H_

./Common/Inc/VgIPlaceListenerWithBubble.h

/*
 * Copyright 2011, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */
#ifndef _VGIPLACELISTENERWITHBUBBLE_H_
#define _VGIPLACELISTENERWITHBUBBLE_H_

#include "Modules/Map/VgIPlaceListener.h"

namespace VgEngine
{
    struct VgPosition;
}

class VgIPlaceListenerWithBubble : public VgMapModule::VgIPlaceListener
{
public:
    
    virtual void notifyPlaceSelected (VgApplication::VgIApplication& pVgApplication, const std::string& pID, const VgEngine::VgPosition& pPosition) = 0;

    virtual void hideBubble () = 0;

    virtual void showBubble (const VgEngine::VgPosition& pPosition, const std::string& pID, const std::string& pMessage) = 0;

protected:
    virtual ~VgIPlaceListenerWithBubble() {}
};

#endif // _VGIPLACELISTENERWITHBUBBLE_H_

./Common/Inc/VgMyAvatarDisplay.h

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

#ifndef _VGMYAVATARDISPLAY_H_
#define _VGMYAVATARDISPLAY_H_

#include <string>

#include "VgEngine/VgPosition.h" 

#include "VgMyNavigationPositionDisplay.h"

namespace VgApplication
{
    class VgIApplication;
};

namespace Vg3DModule
{
    class VgPoint;
};

namespace VgNavigationModule
{
    class VgINavigation;
};

class VgMyTextureLoader;

class VgMyAvatarDisplay : public VgMyNavigationPositionDisplay
{
public:
    VgMyAvatarDisplay(VgApplication::VgIApplication* pVgApplication, VgMyTextureLoader* pTextureLoader, bool pDoesFollowRoute);
    virtual ~VgMyAvatarDisplay();

    /*
    * Implementation of interface : VgMyNavigationPositionDisplay 
    *
    * @note You can customize the avatar's altitude, visibility and its animation here.
    */
    void updateWithPosition(VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigation > const& pNavigation, const VgEngine::VgPosition& pPosition);
    void clear();
    void show();
    void hide();
    bool isVisible();

protected:
    VgApplication::VgIApplication* mVgApplication;
    VgEngine::VgRefPtr< Vg3DModule::VgPoint > mAvatarPoint;
    VgMyTextureLoader* mTextureLoader;
    VgEngine::VgPosition mPosition;
    std::string mLastAvatarLayerName;
    bool mDoesFollowRoute;
    bool mIsAvatarVisible;
};

#endif // _VGMYAVATARDISPLAY_H_

./Common/Inc/VgMyBasicApplicationController.h

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */
#ifndef _VGMYBASICAPPLICATIONCONTROLLER_H_
#define _VGMYBASICAPPLICATIONCONTROLLER_H_

#if _MSC_VER >= 1400 // VC++ 8.0
#pragma warning( disable : 4068 )   // disable warning about strdup being deprecated.
#endif

#include <string>
#include <list>
#include <map>

#include "VgEngine/VgICamera.h"

#include "Modules/Routing/VgIRouteCallback.h"

#include "Modules/Navigation/VgINavigation.h"
#include "Modules/Navigation/VgINavigationCallback.h"
#include "Modules/Navigation/VgINavigationListener.h"

#include "VgMyLayerAndCameraListener.h"
#include "VgMyLayerAndCameraHandler.h"
#include "VgMyRouteCreator.h"
#include "VgMyInstructionUpdateListener.h"
#include "VgMyLocationListener.h"
#include "VgMyRouteCreator.h"
#include "VgMyRouteDisplay.h"

namespace VgApplication 
{
    class VgIApplication;
};

namespace VgEngine
{
    class VgFunctorDescriptor;
};

namespace Vg3DModule
{
    class VgPoint;
};

namespace VgRoutingModule
{
    class VgIRoute;
};

namespace VgNavigationModule 
{
    class VgINavigation;
    class VgINavigationInstruction;
};

class VgMyNavigationCreator;
class VgMyInstructionDisplay;
class VgMyNavigationPositionDisplay;
class VgMyTextureLoader;

class VgMyBasicApplicationController;

class VgMyBasicRouteCallback : public VgRoutingModule::VgIRouteCallback
{
    
public:

    VgMyBasicRouteCallback (VgMyBasicApplicationController* pController);
    
    ~VgMyBasicRouteCallback ();
    
    void notifyRouteComputed( VgRoutingModule::VgRouteRequestStatus pStatus, VgEngine::VgRefPtr< VgRoutingModule::VgIRoute > pRoute);

protected:

    VgMyBasicApplicationController* mController;

};

class VgMyBasicNavigationCallback : public VgNavigationModule::VgINavigationCallback
{

public :

    VgMyBasicNavigationCallback (VgMyBasicApplicationController* pController);
    
    ~VgMyBasicNavigationCallback ();

    bool notifyNavigationComputed(VgNavigationModule::VgNavigationRequestStatus pStatus, VgEngine::VgRefPtr< VgNavigationModule::VgINavigation > pNavigation);

protected:

    VgMyBasicApplicationController* mController;

};

class VgMyBasicNavigationListener : public VgNavigationModule::VgINavigationListener
{

public :

    VgMyBasicNavigationListener (VgMyBasicApplicationController* pController);

    ~VgMyBasicNavigationListener ();

    void notifyPositionUpdated (VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigation > const& pNavigation,const VgEngine::VgPosition &,double);

    void notifyNewInstruction (VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigation > const& pNavigation,unsigned int);

protected:

    VgMyBasicApplicationController* mController;

};

class VgMyBasicApplicationController : 
    public VgMyLayerAndCameraListener, 
    public VgMyLayerAndCameraHandler,
    public VgMyInstructionUpdateListener,
    public VgMyLocationListener,
    public VgMyRouteCreator
{

public:

    VgMyBasicApplicationController(VgApplication::VgIApplication& pApplication, VgMyTextureLoader* pTextureLoader);
    
    virtual ~VgMyBasicApplicationController();
    
    bool loadConfiguration(const std::string& pConfiguration, const unsigned int pSecretKey, const std::string& pLicenseURL, const int pDataset = 0);

    void unloadConfiguration();

    void setLayerAndCameraHandler(VgMyLayerAndCameraHandler* pHandler);

    void setRouteCreator(VgMyRouteCreator* pCreator);
    VgMyRouteCreator* getRouteCreator() const;
    void addRouteDisplay(VgMyRouteDisplay* pDisplay);

    void setNavigationCreator(VgMyNavigationCreator* pCreator);
    void addNavigationPositionDisplay(VgMyNavigationPositionDisplay* pDisplay);
    void addInstructionDisplay(VgMyInstructionDisplay* pDisplay);
    // NOTE : removeNavigationDisplay is not implemented in this sample for simplicity.

    bool has3DModule() const;
    bool hasMapModule() const;
    bool hasRoutingModule() const;
    bool hasNavigationModule() const;

    void addLayerAndCameraListener(VgMyLayerAndCameraListener* pListener);

    void deleteRoute();
    

#pragma mark Implementation of VgMyRouteCreator
    /*
    * Implementation of interface : VgMyRouteCreator 
    */
    bool setRoutePoint(VgMyRouteCreator::RoutePoint pPoint, const std::string& pPlaceID);
    bool setRoutePoint(VgMyRouteCreator::RoutePoint pPoint, const VgEngine::VgPosition& pPosition);
    void resetRoutePoint(VgMyRouteCreator::RoutePoint pPoint);
    bool isRoutePointSet(VgMyRouteCreator::RoutePoint pPoint);
    void computeRoute();
    VgRoutingModule::VgIRouteRequestParameters* editRoutingRequestParameters();
    void resetRoutingRequestParameters();
    virtual VgEngine::VgRefPtr< VgEngine::VgAnimationDescriptor > getRoutePointHighlightAnimationDescriptor ();
    virtual void setAvoidStairs (bool pDisabledFriendly);
#pragma mark --


#pragma mark Implementation of VgMyLayerAndCameraListener
    /*
    * Implementation of interface : VgMyLayerAndCameraListener 
    */
    void layerWillChangeFrom(VgMyLayerAndCameraHandler* pSender, const std::string& pFloorFrom, const std::string& pFloorTo);
    void layerChangedTo(VgMyLayerAndCameraHandler* pSender, const std::string& pFloorFrom, const std::string& pFloorTo);
    void viewWillChange(VgMyLayerAndCameraHandler* pSender, const bool pDoesChangeFromGlobalToDetailed);
    void viewDidChange(VgMyLayerAndCameraHandler* pSender, const bool pDoesChangeFromGlobalToDetailed);
    
#pragma mark --
    

#pragma mark Implementation of VgMyInstructionUpdateListener
    /*
    * Implementation of interface : VgMyInstructionUpdateListener 
    */
    void goToInstruction(const unsigned int pInstructionIndex);
#pragma mark --


#pragma mark Implementation of VgMyLayerAndCameraHandler
    /*
    * Implementation of interface : VgMyLayerAndCameraHandler 
    */
    bool isGlobalView();
    void switchToGlobalView(bool pIsAnimated = true);
    void switchToDetailedView(bool pIsAnimated = true);
    const std::string& getFocusedLayerName();
    void gotoLayer(const std::string& pLayerName, bool pIsAnimated = true);
    void gotoLayer(const unsigned int pLayerIndex, bool pIsAnimated = true);
    unsigned int getNumberOfLayers();
    bool getLayerName(const unsigned int pLayerIndex, std::string& pLayerNameOut);
    void gotoViewpoint(const VgEngine::VgIViewPoint& pViewPoint, const std::string& pLayerName, bool pIsAnimated = true);
    void gotoLookAtPosition(const VgEngine::VgPosition& pPosition, const std::string& pLayerName, bool pIsAnimated = true);
    
    void refreshParameters(unsigned int pWidth, unsigned int pHeight);
#pragma mark --


#pragma mark Implementation of VgRoutingModule::VgIRouteCallback
    /*
    * Implementation of interface : VgRoutingModule::VgIRouteCallback 
    */
    void notifyRouteComputed (VgRoutingModule::VgRouteRequestStatus pStatus, VgEngine::VgRefPtr< VgRoutingModule::VgIRoute > const& pRoute);
#pragma mark --


#pragma mark Implementation of VgNavigationModule::VgINavigationCallback
    /*
    * Implementation of interface : VgNavigationModule::VgINavigationCallback 
    */
    bool notifyNavigationComputed (VgNavigationModule::VgNavigationRequestStatus pStatus, VgEngine::VgRefPtr< VgNavigationModule::VgINavigation > const& pNavigation);
#pragma mark --
    
    
#pragma mark Implementation of VgNavigationModule::VgINavigationListener
    /*
    * Implementation of interface : VgNavigationModule::VgINavigationListener 
    */
    void notifyPositionUpdated(VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigation > const& pNavigation, const VgEngine::VgPosition& pPosition, double pTime);
    void notifyNewInstruction(VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigation > const& pNavigation, unsigned int pIndex);
#pragma mark --
    
#pragma mark Implementation of VgMyLocationListener
    /*
     * Implementation of interface : VgMyLocationListener 
     */
    void updatePosition(const VgEngine::VgPosition& pPosition);
#pragma mark --
    
    void clearNavigationPositionDisplays();
    
    VgEngine::VgRefPtr< VgRoutingModule::VgIRouteCallback > getRouteCallback()
    {
        return mRouteCallback;
    }

    virtual void setRouteStyle (VgMyRouteStyler::RouteStyle pRouteStyle, bool pRecomputeRoute = true);
    
    VgMyRouteStyler::RouteStyle getRouteStyle () const;

protected:

    void animateToInstruction(VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigation > const& pNavigation, unsigned int pIndex);

    VgApplication::VgIApplication& mVgApplication;

    VgMyLayerAndCameraHandler* mLayerAndCameraHandler;

    VgMyRouteCreator* mRouteCreator;
    VgMyNavigationCreator* mNavigationCreator;

    std::list<VgMyLayerAndCameraListener*> mLayerAndCameraListeners;

    std::list<VgMyRouteDisplay*> mRouteDisplays;
    std::list<VgMyNavigationPositionDisplay*> mPositionDisplays;
    std::list<VgMyInstructionDisplay*> mInstructionsDisplays;

    VgEngine::VgRefPtr< VgRoutingModule::VgIRoute > mRoute;

    VgEngine::VgRefPtr< VgNavigationModule::VgINavigation > mNavigation;

    unsigned int mMaximumInstructionNumber;         // Maximum number of instructions returned by the navigation guidance.

    VgMyTextureLoader* mTextureLoader;

    VgEngine::VgRefPtr< VgMyBasicRouteCallback > mRouteCallback;

    VgEngine::VgRefPtr< VgMyBasicNavigationCallback > mNavigationCallback;

    VgEngine::VgRefPtr< VgMyBasicNavigationListener > mNavigationListener;

};

#endif // _VGMYBASICAPPLICATIONCONTROLLER_H_

./Common/Inc/VgMyFloorPoiCallback.h

/*
 * Copyright 2011, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

#ifndef _VGMYFLOORPOICALLBACK_H_
#define _VGMYFLOORPOICALLBACK_H_

#include "Modules/3D/VgIGeometryCallback.h"
#include "VgEngine/VgPosition.h"
#include <string>

namespace VgEngine
{
    class VgICamera;
};

namespace Vg3DModule
{
    class VgIGeometryEvent;
}

class VgMyLayerAndCameraHandler;

class VgMyFloorPoiCallback : public Vg3DModule::VgIGeometryCallback
{
public:
    VgMyFloorPoiCallback(VgMyLayerAndCameraHandler* pHandler, VgEngine::VgICamera* pCamera, const VgEngine::VgPosition& pPosition, const std::string& pLayerName);

    virtual ~VgMyFloorPoiCallback();
    
    virtual void handleGeometryEvent (const Vg3DModule::VgIGeometryEvent& pEvent);

protected:
    VgMyLayerAndCameraHandler* mHandler;
    VgEngine::VgICamera* mCamera;
    VgEngine::VgPosition mGoToPos;
    std::string mLayerName;
};

#endif // _VGMYFLOORPOICALLBACK_H_

./Common/Inc/VgMyInstructionPathDisplay.h

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

#ifndef _VGMYINSTRUCTIONPATHDISPLAY_H_
#define _VGMYINSTRUCTIONPATHDISPLAY_H_

#if _MSC_VER >= 1400 // VC++ 8.0
#pragma warning( disable : 4068 )   // disable warning about pragma.
#endif

#include "VgMyInstructionDisplay.h"

#include "VgEngine/VgPosition.h"

namespace VgApplication
{
    class VgIApplication;
};

namespace Vg3DModule
{
    class VgLine;
}

namespace VgNavigationModule
{
    class VgINavigation;
    class VgINavigationInstruction;
}

class VgMyInstructionPathDisplay : public VgMyInstructionDisplay
{
public:
    VgMyInstructionPathDisplay (VgApplication::VgIApplication* pVgApplication);
    virtual ~VgMyInstructionPathDisplay ();

#pragma mark Implementation of VgMyInstructionDisplay

    void updateWithInstruction(VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigation > const& pNavigation, unsigned int pIndex);
    void clear();
    void show();
    void hide();
    bool isVisible();
#pragma mark --

protected:
    VgApplication::VgIApplication* mVgApplication;
    VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigationInstruction > mInstruction;
    VgEngine::VgRefPtr< Vg3DModule::VgLine > mLine;
    bool mIsLineVisible;
};

#endif // _VGMYINSTRUCTIONPATHDISPLAY_H_

./Common/Inc/VgMyNavigationHelper.h

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */
#ifndef _VGMYNAVIGATIONHELPER_H_
#define _VGMYNAVIGATIONHELPER_H_

#if _MSC_VER >= 1400 // VC++ 8.0
#pragma warning( disable : 4068 )   // disable warning about pragma.
#endif

#include "Interfaces/VgMyNavigationCreator.h"
#include "Modules/Navigation/VgINavigationInstruction.h"

#include <string>

namespace VgMapModule
{
    class VgIMapModule;
}

namespace VgNavigationModule
{
    class VgINavigation;
    class VgINavigationModule;
    struct VgINavigationRequestParameters;
}

class VgMyNavigationHelper : public VgMyNavigationCreator
{
public:

    enum StringType
    {
        eStringFor,
        eStringThen,
        eStringAnd,
        eStringNear,
        eStringUsing,
        eStringCount,
    };

    struct VgTranslatedInstruction
    {
        std::string mBrief;
        std::string mMessage;
        std::string mDuration;
        float mDurationInSeconds;
    };

    VgMyNavigationHelper(VgNavigationModule::VgINavigationModule* pNavModule);
    
    virtual ~VgMyNavigationHelper();

#pragma mark Implementation of VgMyNavigationCreator

    void createNavigation(VgNavigationModule::VgINavigationRequestParameters& pParameters);
#pragma mark --

    static void translateInstruction(
        VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigationInstruction > const & pInstruction,
        VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigation > const& pNavigation,
        VgTranslatedInstruction& pTranslated,
        VgMapModule::VgIMapModule& pMapModule,
        int pLang = 0);

    static int getLangId (const std::string& pLangSr);

protected:

    static std::string timeToText (float pTimeInMinutes, int pLang);
    
    static void replaceTokens(
        std::string& pStringWithTokens,
        VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigationInstruction > const & pInstructionCurrent,
        VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigationInstruction > const & pInstructionNext);

    VgNavigationModule::VgINavigationModule* mNavigationModule;

    static const std::string cLanguageStrings [2];

    static const size_t cNumLanguages = sizeof(cLanguageStrings)/sizeof(std::string);

    static const std::string cActionStringTable[cNumLanguages][VgNavigationModule::eVgManeuverTypeMax];

    static const std::string cNextActionStringTable[cNumLanguages][VgNavigationModule::eVgManeuverTypeMax];

    static const std::string cTimeStringTable [cNumLanguages][3];
    
    static const std::string cStringTable[cNumLanguages][eStringCount];

};

#endif // _VGMYNAVIGATIONHELPER_H_

./Common/Inc/VgMyRoutingHelper.h

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */
#ifndef _VGMYROUTINGHELPER_H_
#define _VGMYROUTINGHELPER_H_

#if _MSC_VER >= 1400 // VC++ 8.0
#pragma warning( disable : 4068 )   // disable warning about pragma.
#endif

#include <map>
#include <list>
#include <string>

#include "VgMyPoiConfigurationSetter.h"
#include "VgMyRouteCreator.h"
#include "VgMyRouteDisplay.h"
#include "VgMyRouteStyler.h"

#include "VgEngine/VgFunctorDescriptor.h"

#include "Modules/Map/VgIMapModule.h"

#include "Modules/3D/VgIconMarkerDescriptor.h"
#include "Modules/3D/VgIGeometryCallback.h"
#include "Modules/3D/VgLine.h"
#include "Modules/3D/VgPoint.h"

#include "VgMyRouteStyler.h"

namespace VgApplication
{
    class VgIApplication;
};

namespace VgEngine
{
    class VgInstanceFactory;
    class VgITexture;
};

namespace Vg3DModule
{
    class VgIGeometryCallback;
    class VgLink;
};

namespace VgRoutingModule
{
    class VgIRoute;
    class VgIRouteCallback;
    class VgIRouteConverter;
    class VgIRoutingModule;
    class VgIRoutingSolver;
};

class VgMyLayerAndCameraHandler;
class VgMyTextureLoader;

class VgMyRoutingHelper : public VgMyRouteCreator, public VgMyRouteDisplay, public VgMyPoiConfigurationSetter
{

public:

    VgMyRoutingHelper (VgApplication::VgIApplication* pVgApplication, VgMyTextureLoader* pTextureLoader, VgEngine::VgRefPtr< VgRoutingModule::VgIRouteCallback >const& pCallback, VgMyLayerAndCameraHandler* pLayerAndCamerHandler);
    
    virtual ~VgMyRoutingHelper();

#pragma mark Implementation of VgMyRouteCreator

    virtual bool setRoutePoint(VgMyRouteCreator::RoutePoint pPoint, const std::string& pPlaceID);
    virtual bool setRoutePoint(RoutePoint pPoint, const VgEngine::VgPosition& pPosition);
    virtual void resetRoutePoint(VgMyRouteCreator::RoutePoint pPoint);
    virtual bool isRoutePointSet(VgMyRouteCreator::RoutePoint pPoint);
    virtual void computeRoute();
    virtual VgRoutingModule::VgIRouteRequestParameters* editRoutingRequestParameters();
    virtual void resetRoutingRequestParameters();
    virtual void setAvoidStairs(bool pDisabledFriendly);
    VgEngine::VgRefPtr< VgEngine::VgAnimationDescriptor > getRoutePointHighlightAnimationDescriptor ();
    std::vector< VgEngine::VgPosition > simplifyForWidth (const std::vector< VgEngine::VgPosition >& pPositions, double pWidth);

#pragma mark --

    #pragma mark Implementation of VgMyRouteDisplay

    bool createRouteObjects(VgEngine::VgConstRefPtr< VgRoutingModule::VgIRoute > const& pRoute);
    void clear();
    void show();
    void hide();
    bool isVisible();
#pragma mark --

    #pragma mark Implementation of VgMyPoiConfigurationSetter
    /*
    * Implementation of interface : VgMyPoiConfigurationSetter 
    */
    void setPoiCallback(const std::string& pIdentifier, VgEngine::VgRefPtr< Vg3DModule::VgIGeometryCallback >const& pCallback);
#pragma mark --


    // Use these static strings to set custom callback when the associated POIs are clicked.
    static const std::string kStartPointStrID; // "VgMyRoutingHelper_StartPoint"
    static const std::string kEndPointStrID;   // "VgMyRoutingHelper_EndPoint"

    /*
     * Change the routing style of lines generated by the routing helper.
     * @param pRouteStyle route style
     * @param pRecomputeRoute
     */
    void setRouteStyle (VgMyRouteStyler::RouteStyle pRouteStyle, bool pRecomputeRoute = true);
    
    /*
     * get the current route style
     * @return current route style.
     */
    VgMyRouteStyler::RouteStyle getRouteStyle() const;
    
    
protected:

    // Holds information on Lines to ease show/hide
    struct LineObject
    {
        LineObject() 
            : line(NULL)
            , hasBeenAdded(false)
        {}

        VgEngine::VgRefPtr< Vg3DModule::VgLine > line;
        std::string layerName;
        bool hasBeenAdded;
    };
    
    // Holds information on Points to ease show/hide
    struct PointObject
    {
        PointObject()
            : point(NULL)
            , callback(NULL)
            , isExternalCallback(false)
        {}

        VgEngine::VgRefPtr< Vg3DModule::VgPoint > point;
        VgEngine::VgRefPtr< Vg3DModule::VgIGeometryCallback > callback;
        std::string layerName;
        bool isExternalCallback;
    };

    double computeFloorHeightFromLayer (const std::string& pLayer) const;

    bool isPlaceRoutable (const std::string& pID);

    bool isPositionRoutable (const VgEngine::VgPosition& pPosition);

    void requestRoute (const VgEngine::VgRefPtr<VgRoutingModule::VgIRoutingNode> pOrigin, const VgEngine::VgRefPtr<VgRoutingModule::VgIRoutingNode> pDestination);
    
    
    void createAndAddRouteMarker(VgMyRouteCreator::RoutePoint pPoint, const VgEngine::VgPosition& pPosition);
    
    void removeRouteMarkers();
    
    std::string getLayerNameForPosition(VgEngine::VgPosition pPosition);
    
    VgEngine::VgPosition getPositionOfPlace(const std::string& pPlaceId);

    VgApplication::VgIApplication* mVgApplication;
    VgEngine::VgInstanceFactory* mInstanceFactory;

    VgMyTextureLoader* mTextureLoader;
    VgEngine::VgRefPtr< VgRoutingModule::VgIRouteCallback > mCallback;

    std::map<VgMyRouteCreator::RoutePoint, VgEngine::VgRefPtr<VgRoutingModule::VgIRoutingNode> > mRoutePoints;
    VgRoutingModule::VgIRouteRequestParameters mRoutingRequestParameters;

    VgRoutingModule::VgIRoutingModule* mRoutingModule;
    VgRoutingModule::VgIRoutingSolver* mRouteSolver;
    VgRoutingModule::VgIRouteConverter* mRouteConverter2D;
    
    VgMapModule::VgIMapModule* mMapModule;
    
    std::map<VgMyRouteCreator::RoutePoint, VgEngine::VgRefPtr< Vg3DModule::VgPoint > > mHighlightedRoutePoints;

    bool mIsRouteVisible;

    VgMyRouteStyler::RouteStyle mRouteStyle;

    std::vector< PointObject > mPoints;
    std::list< VgEngine::VgRefPtr< Vg3DModule::VgLink > > mLinks;
    std::vector< LineObject > mLines;

    // Registred callbacks for route Points
    typedef std::map<std::string, VgEngine::VgRefPtr< Vg3DModule::VgIGeometryCallback > > POICallbackMap;
    POICallbackMap mRoutePoiCallbacks;

    float mObjectHeightOffset;

    VgMyLayerAndCameraHandler* mLayerAndCameraHandler;

    VgEngine::VgRefPtr< VgEngine::VgAnimationDescriptor > mHighlightedRoutePointsAnimationDescr;

    VgMyRouteStyler mRouteStyler;

};

#endif // _VGMYROUTINGHELPER_H_

./Common/Inc/VgMyStackedLayerAndCameraHandler.h

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

#ifndef _VGMYSTACKEDLAYERANDCAMERAHANDLER_H_
#define _VGMYSTACKEDLAYERANDCAMERAHANDLER_H_

#if _MSC_VER >= 1400 // VC++ 8.0
#pragma warning( disable : 4068 )   // disable warning about pragma.
#endif

#include "VgMyLayerAndCameraHandler.h"
#include "VgStringHashMap.h"

#include "VgApplication/VgISimpleGestureManipulatorListener.h"

#include "VgEngine/VgIAnimationCallback.h"
#include "VgEngine/VgIEngine.h"

#include <time.h>

namespace VgApplication
{
    class VgIApplication;
};

namespace VgEngine
{
    class VgIAnimationCallback;
    class VgLayer;
};

class FloorSelectorManipulator;
class VgMyLayerAndCameraListener;
class VgMyStackedLayerAndCameraHandler;



class FloorSelectorManipulator : public VgApplication::VgISimpleGestureManipulatorListener
{

public:

    FloorSelectorManipulator(VgApplication::VgIApplication* pApplication, VgMyStackedLayerAndCameraHandler* pSelector, unsigned int pViewWidthInPixels, unsigned int pViewHeightInPixels);

    virtual ~FloorSelectorManipulator();

    virtual void onSimplePinch(const VgEngine::VgGestureState pState, const float pSpan, const float pVelocity);

    virtual void onSimpleDrag(const VgEngine::VgGestureState pState, const unsigned int pNbTouch, const float pAverageXOffset, const float pAverageYOffset);

    virtual void onClick (float x, float y);
    
    virtual void onDoubleClick (float x, float y);

    void setViewSize(unsigned int pWidth, unsigned int pHeight);

protected:

    void cancelDragGesture();

    void cancelPinchGesture();

    VgMyStackedLayerAndCameraHandler* mSelector;

    VgApplication::VgIApplication* mApplication;

    int mDragTotalOffsetY;
    
    bool mDragGestureStarted;
    
    bool mPinchGestureStarted;
    
    unsigned int mViewSize[2];
    
    float mOriginalSpan;

};

class VgMyStackedLayerAndCameraHandler : public VgMyLayerAndCameraHandler
{
public:
    
    /*
     * The below enum represents parameters that can be configured to
     * change the behaviour of the VgMyStackedLayerAndCameraHandler object.
     */
    typedef enum VgMyConfigurableParam
    {
        /*
         * This distance will be applied to the layers which are neighbouring 
         * the current layers when in detailed view.
         */
        eFarAwayHeight,
        /*
         * Heading used when the stack is displayed.  
         * Note: The default heading comes from "yaw" attribute of the "camera"
         * tag within the bundles configuration file.
         */
        eStackViewHeading,
        /*
         * Pitch used when the stack is displayed
         */
        eStackViewPitch,        
        /*
         * The maximum distance (meters) across the dataset.
         * Setting this parameter will automatically reset the following parameters:
         * - eStackViewDistance
         * - eLayerDistance
         * - eLayerDistanceFromCurrent
         * Note the default max size is calculated from the limits of the dataset 
         * indicated by the bundles configuration file.
         */
        eLayerMaxSize,
        /*
         * Distance between the camera and the layer stack.  
         *
         * Note: This param will be re-calculated automatically given the following conditions
         * - when eLayerMaxSize is set.
         * - when the refreshParameters(pWidth, pHeight) is called.
         *
         * When this value is calculated automatically, the camera will be displaced
         * just far enough away to ensure that the width of the eLayerMaxSize will fit
         * within the available view width.
         */
        eStackViewDistance,
        /*
         * Distance between layers (except ones around the current)
         *
         * Note: This param will be re-calculated automatically given the following conditions
         * - when eLayerMaxSize is set.
         * - when the refreshParameters(pWidth, pHeight) is called. 
         */
        eLayerDistance,
        /*
         * Distance between layers around the current
         *
         * Note: This param will be re-calculated automatically given the following conditions
         * - when eLayerMaxSize is set.
         * - when the refreshParameters(pWidth, pHeight) is called. 
         */
        eLayerDistanceFromCurrent, 
        /*
         * Duration of of camera animation when moving to detailed view.
         * Note : camera animation duration must be <= layer animation duration 
         * due to the manipulator change at the end of layers animation.
         */
        eAnimateToDetailCameraDuration,
        /*
         * Duration of camera animation when moving to global view  (seconds).
         */
        eAnimateToGlobalCameraDuration,
        /*
         * Duration of layer animation when moving to global view  (seconds).
         */
        eAnimateToGlobalLayerDuration,
        /*
         * See note assocated with eAnimateToDetailCameraDuration to see 
         * restrictions associated with this value  (seconds).
         */
        eAnimateToDetailLayerDuration,
        /*
         * Duration of animation when changing layer within the global view (seconds).
         */
        eAnimateChangeOfLayerDuration,
        /*
         * Duration of animation when cancelling a pinch gesture (seconds). 
         */
        eAnimateCancelPinchDuration,
        /*
         * Duration of animation when cancelling a drag gesture (seconds).
         */
        eAnimateCancelDragDuration,
        /*
         * Limits the maximum possible duration when animating to a view point
         */
        eAnimateMaxViewPointDuration, 
        /*
         * This threshold determines how long a drag is required in the global stack view before
         * the current layer is changed.
         * Measured as a percentage value [0.0 - 1.0] of the views pixel.
         */
        eChangeLayerTriggerThreshold,
        /*
         * Angle on stack view for non active layer (in degrees)
         */
        eStackNonActiveLayerAngle,
        /*
         * Angle on stack view for non active layer (in degrees)
         */
        eStackActiveLayerAngle,        
        /*
         * DO NOT USE
         */
        eMaxDoubleParams
    } VgMyConfigurableParam;
    
    VgMyStackedLayerAndCameraHandler(VgApplication::VgIApplication* pVgApplication, VgMyLayerAndCameraListener* pListener, unsigned int pViewWidthInPixels, unsigned int pViewHeightInPixels);
    virtual ~VgMyStackedLayerAndCameraHandler();

#pragma mark Implementation of VgMyLayerAndCameraHandler
    /*
    * Implementation of interface : VgMyLayerAndCameraHandler 
    */
    bool isGlobalView();
    void switchToGlobalView(bool pIsAnimated = true);
    void switchToDetailedView(bool pIsAnimated = true);

    const std::string& getFocusedLayerName();
    void gotoLayer(const std::string& pLayerName, bool pIsAnimated = true);
    unsigned int getNumberOfLayers();
    bool getLayerName(const unsigned int pLayerIndex, std::string& pLayerNameOut);
    void gotoLayer(const unsigned int pLayerIndex, bool pIsAnimated = true);
    void gotoViewpoint(const VgEngine::VgIViewPoint& pViewpoint, const std::string& pLayerName, bool pIsAnimated = true);
    void gotoLookAtPosition(const VgEngine::VgPosition& pPosition, const std::string& pLayerName, bool pIsAnimated = true);
    void refreshParameters(unsigned int pWidth, unsigned int pHeight);

    unsigned int getCurrentLayerIndex() const;
    
#pragma mark --
#pragma mark Methods to configure the stack view
    
    VgEngine::VgPosition* getCameraPosition();

    void onLayerSelected();

    void onSelectorReady();

    void animateCameraToViewPoint(const VgEngine::VgIViewPoint& pViewPoint, float pDuration, bool pIsAnimated);
    
    enum eFromToViewEnum
    {
        eFromStackToDetailedView,
        eFromDetailedToStackView,
        eFromGlobalToGlobaView // Used by cancel drag.
    };
    void animateLayersFromCloseToStackView(eFromToViewEnum pDirection, float pDuration, bool pIsAnimated);
    
    VgEngine::VgPosition getPositionForLayerInGlobalView(unsigned int pLayerIndex, unsigned int pFocusedLayer);
    
    
    VgEngine::VgPosition getPositionForLayerInDetailedView(unsigned int pLayerIndex, unsigned int pFocusedLayer);
    
    void animateLayerToPositionAndRotation(VgEngine::VgRefPtr< VgEngine::VgLayer >const& pLayer,
                                           const VgEngine::VgPosition& pStartPos,
                                           const VgEngine::VgPosition& pEndPos,
                                           VgEngine::VgRefPtr< VgEngine::VgIAnimationCallback >const& pCallback,
                                           float pDuration,
                                           float pStartAngle,
                                           float pEndAngle);

    
    VgEngine::VgIViewPoint& getStackViewPoint();
    
    /*
     * Sets the stack center position.  The stack center position is shared by all the layer
     * that make up the stack.
     */ 
    void setStackCenterPosition(const VgEngine::VgPosition& pCenter);
    
    const VgEngine::VgPosition& getStackCenter();
    
    /*
     * Force the global stack view to redraw it self.  Needs to be called after having
     * changed any of the configurable parameters.
     */
    void refreshStackView();
    
    void setParam(const VgMyConfigurableParam pParam, const double pDouble);
    
    double getParam(const VgMyConfigurableParam pParam);
    
    void updateManipulatorForGlobalView(bool pIsGlobalView);
    
protected:

    // if set to false, it will use single click to switch views.  if true it will use zoom.
    bool mUsePinchToSwitchGlobalToDetailed;

    VgEngine::VgRefPtr< VgEngine::VgIAnimationCallback > registerCallback(VgEngine::VgRefPtr< VgEngine::VgIAnimationCallback > pCallback, unsigned int pLayerIndex);
    void setDefaultStackParams();
    void calculateDynamicStackParams();
    void gotoLayerInGlobalView(const unsigned int pLayerIndex, bool pIsAnimated);
    void gotoLayerInDetailedView(const unsigned int pLayerIndex, bool pIsAnimated);
    

    VgApplication::VgIApplication* mVgApplication;
    VgMyLayerAndCameraListener* mLayerUpdateListener;

    unsigned int mCurrentLayerIndex;
    unsigned int mPreviousLayerIndex;
    bool mIsLayerStackDisplayed;
    bool mIsViewModeInitialized;
    
    VgEngine::VgIViewPoint mCamStartViewPoint;  // Viewpoint used in single layer view
    
    // Contains all configurable parameters related to this object.
    // see the setParam and getParam methods for more details.
    double mParam[eMaxDoubleParams];

    VgEngine::VgPosition mStackCenter;  // Center of the stack
    VgEngine::VgIViewPoint mCameraGlobalViewPoint;  // Camera's view point when in global stack mode.
    
    VgEngine::VgRefPtr< VgEngine::VgIAnimationCallback > mCameraCallback; // Camera Animation callback. Callbacks must be freed manually.
    
    std::vector<VgEngine::VgRefPtr< VgEngine::VgIAnimationCallback > > mLayersCallback; // Layer Animation callbacks. Callbacks must be freed manually.
    VgEngine::VgRefPtr< FloorSelectorManipulator > mManipulatorListener;
    
    std::hash_map<std::string, float> mLODsFactors;
    std::hash_map<std::string, float> mLoadFactors;
};

#endif // _VGMYSTACKEDLAYERANDCAMERAHANDLER_H_

./Common/Inc/VgMyTextureLoader.h

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

#ifndef _VGMYTEXTURELOADER_H_
#define _VGMYTEXTURELOADER_H_

#include <string>
#include <vector>
#include "VgStringHashMap.h"
#include "VgEngine/VgRefPtr.h"

#include "Modules/3D/VgIconMarkerDescriptor.h"

namespace VgApplication
{ 
    class VgIApplication;
};

namespace VgEngine
{
    class VgITexture;
};

/*
* Provides easy access to textures and icon markers used by the application.
*
* Textures and markers are shared and lazily loaded (on first time use)
*/
class VgMyTextureLoader
{
public:
    VgMyTextureLoader(VgApplication::VgIApplication* pVgApplication, const std::string& pImageResourceDirectory);

    virtual ~VgMyTextureLoader();

    struct ImageCache
    {
        
        ImageCache ();

        bool mIsSet;

        bool mTriedToLoad;

        std::string mFilename;

        VgEngine::VgRefPtr< VgEngine::VgITexture > mTexture;

    };    
    
    std::hash_map<std::string, ImageCache> mImageCache;
    
    struct MarkerCache
    {

        MarkerCache ();

        std::string imageName;

        bool mTriedToLoad;

        VgEngine::VgRefPtr< Vg3DModule::VgIconMarkerDescriptor > marker;

    };

    std::hash_map<std::string, MarkerCache> mMarkerCache;

    VgEngine::VgRefPtr< VgEngine::VgITexture > getTextureBuffer (const std::string& pImageName);

    VgEngine::VgRefPtr< Vg3DModule::VgIconMarkerDescriptor > getMarker(const std::string& pMarkerName);

    void setImage (const std::string& pImageName, const std::string& pFilename);

    void setMarker (const std::string& pMarkerName, const std::string& pImageName);

    void resetImage(const std::string& pImageName);
    
    void resetImage(std::hash_map< std::string, ImageCache >::iterator pImageIter);

    void resetMarker(const std::string& pType);
    
    void resetMarker(std::hash_map< std::string, MarkerCache >::iterator pMarkerIter);

    bool isImageSet(const std::string& pImageName) const;

    bool isMarkerSet(const std::string& pMarkerName) const;

protected:

    VgApplication::VgIApplication* mVgApplication;
    
    std::string mImageResourceDirectory;

};

#endif // _VGMYTEXTURELOADER_H_

./Common/Src/Apple/VgMyBubbleView.mm

/*
 * Copyright 2011, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

#import "VgMyBubbleView.h"

#import <QuartzCore/QuartzCore.h>

#include "VgEngine/VgICamera.h"
#include "VgEngine/VgIEngine.h"
#include "VgEngine/VgTypes.h"

#include "VgApplication/VgIApplication.h"
#include "VgApplication/VgIModuleManager.h"

#include "Modules/Map/VgIMapModule.h"
#include "Modules/Map/VgPlaceDescriptor.h"

#include "VgMyRouteCreator.h"



ViewRepositionPostDrawCallback::ViewRepositionPostDrawCallback(UIView* pView, VgEngine::VgICamera* pCamera, const VgEngine::VgPosition& pPosition)
:
mView(pView),
mCamera(pCamera),
mPosition(pPosition)
{}

void ViewRepositionPostDrawCallback::ViewRepositionPostDrawCallback::postDraw (VgEngine::VgIEngineContext* pContext)
{
    // An example, where the object stays on the screen.
    
    UIView* lParent = [mView superview];
    if ( lParent )
    {
        CGRect lSize = lParent.frame;
        
        CGFloat lFrameHalfHeight = mView.frame.size.height / 2;
        double lX, lY, lZ;
        mCamera->projectOnScreen(mPosition, lX, lY, &lZ);
        CGPoint lCenter = CGPointMake(lX * lSize.size.width, (1.0 - lY) * lSize.size.height);
        
        if ( lCenter.x < 0 )
        {
            lCenter.x = 0;
        }
        if ( lCenter.x > lSize.size.width )
        {
            lCenter.x = lSize.size.width;
        }
        if ( lCenter.y < lFrameHalfHeight )
        {
            lCenter.y = lFrameHalfHeight;
        }
        if ( lCenter.y > lSize.size.height )
        {
            lCenter.y = lSize.size.height;
        }
        
        lCenter.y -= lFrameHalfHeight;
        mView.center = lCenter;
        mView.hidden = NO;
    }
}



@implementation VgMyBubbleView

@synthesize mLabelBack;
@synthesize mLabelFront;
@synthesize mButtonLeft;
@synthesize mButtonRight;
@synthesize mInfoWebView;
@synthesize mBubbleViewFront;
@synthesize mBubbleViewBack;
@synthesize mBubbleViewContainer;
@synthesize mRouteEndButton;
@synthesize mRouteStartButton;
@synthesize mPlaceID;

-(id) initWithEngine:(VgEngine::VgIEngine*)pEngine 
            position:(const VgEngine::VgPosition &) pPosition 
              withID:(const std::string &)pID
         withRouting:(BOOL) pIsRoutingEnabled
withRouteCreator:(VgMyRouteCreator *)pRouteCreator
{
    // The frame size will be taken from the top level view of the nib file.
    CGRect lFrame = CGRectMake(0, 0, 0, 0);
    if ((self = [super initWithFrame:lFrame]))
    {
        self.mPlaceID = [NSString stringWithUTF8String:pID.c_str()];
        mEngine = pEngine;
        VgEngine::VgPosition lDialogPoint = VgEngine::VgPosition(pPosition);
        mRouteCreator = pRouteCreator;

        // We'll let the ViewRepositionPostDrawCallback properly place the image view after the first renderscene.
        self.opaque = NO;
        self.hidden = YES;

        std::string lPlaceName = pID;
         
         NSArray* lNibArray = [[NSBundle mainBundle] loadNibNamed:@"VgMyBubbleView" owner:self options:nil];
         for ( UIView* lView in lNibArray )
         {
             lView.opaque = NO;
         }
         
         self.frame = mBubbleViewContainer.frame;
         mBubbleViewContainer.autoresizingMask = UIViewAutoresizingNone;
         self.autoresizingMask = UIViewAutoresizingNone;
         
         
         NSArray* lNibArrayFront = [[NSBundle mainBundle] loadNibNamed:@"VgMyBubbleViewFront" owner:self options:nil];
         for ( UIView* lView in lNibArrayFront )
         {
             lView.opaque = NO;
         }
         mBubbleViewFront.autoresizingMask = UIViewAutoresizingNone;
         
         NSArray* lNibArrayBack = [[NSBundle mainBundle] loadNibNamed:@"VgMyBubbleViewBack" owner:self options:nil];
         for ( UIView* lView in lNibArrayBack )
         {
             lView.opaque = NO;
         }
         mBubbleViewBack.autoresizingMask = UIViewAutoresizingNone;
         
         // Add the appropriate html content to the info view
         [self loadInfoView];
         
         [mBubbleViewContainer addSubview:mBubbleViewFront];
         [self addSubview:mBubbleViewContainer];
         
         // We'll let the ViewRepositionPostDrawCallback properly place the image view after the first renderscene.
         self.opaque = NO;
         self.hidden = YES;
        
        // Set localized title of buttons
        NSString* lSetOriginTitle = nil;
        NSString* lSetDestinationTitle = nil;
        
        NSString* lTbPath = [NSString stringWithFormat:@"%@%@", [[NSBundle mainBundle] bundlePath], @"/Toolbox.bundle"];
        NSBundle* lTbBundle = [NSBundle bundleWithPath:lTbPath];
        if (lTbBundle)
        {
            lSetOriginTitle = NSLocalizedStringFromTableInBundle(@"Set Origin", nil, lTbBundle, nil);
            lSetDestinationTitle = NSLocalizedStringFromTableInBundle(@"Set Destination", nil, lTbBundle, nil);
        }
        else
        {
            // If Toolbox.bundle does not exist use the application bundle.
            // If it does not exist, the Title will be the same as the key.
            lSetOriginTitle = NSLocalizedString(@"Set Origin", nil);
            lSetDestinationTitle = NSLocalizedString(@"Set Destination", nil);
        }
        [mRouteStartButton setTitle:lSetOriginTitle forState:UIControlStateNormal];
        [mRouteEndButton setTitle:lSetDestinationTitle forState:UIControlStateNormal];

        // Set button enabled if routing is possible.
        [mRouteStartButton setEnabled:pIsRoutingEnabled];
        [mRouteEndButton setEnabled:pIsRoutingEnabled];
        
        /*
         * There are no rounded buttons on iOS7, to work around this, we make the text white to keep it readable.
         * There are many other solutions.
         * fixes #4719.
         */
        UIDevice* lDevice = [UIDevice currentDevice];
        int lMajorVersion = [[[lDevice.systemVersion componentsSeparatedByString:@"."] objectAtIndex:0] intValue];
        if (lMajorVersion >= 7)
        {
            mRouteStartButton.backgroundColor = [UIColor whiteColor];
            mRouteEndButton.backgroundColor = [UIColor whiteColor];
        }
        
        mCallback = new ViewRepositionPostDrawCallback((UIImageView*)self, pEngine->editCamera(), lDialogPoint);
        pEngine->addPostDrawCallback(mCallback);
        
        // Set the label at the end, once the object has been loaded.
        mLabelFront.text = [NSString stringWithFormat:@"%s", lPlaceName.c_str()];
        mLabelBack.text = [NSString stringWithFormat:@"%s", lPlaceName.c_str()];
    }
    return self;
}

-(void) clearCallback
{
    if ( mCallback.isValid() )
    {
        mEngine->removePostDrawCallback(mCallback);
        mCallback = NULL;
    }
}

-(IBAction) closeFrame:(UIButton*)sender
{
    [self removeFromSuperview];
    [self clearCallback];
}

-(IBAction)setRouteStart
{
    if (mRouteCreator)
    {
        std::string lPlace([mPlaceID UTF8String]);
        mRouteCreator->setRoutePoint(VgMyRouteCreator::eStart, lPlace);
    }
    
    // Get rid of callout.
    [self closeFrame:nil];
}


-(IBAction)setRouteEnd
{
    if (mRouteCreator)
    {
        std::string lPlace([mPlaceID UTF8String]);
        mRouteCreator->setRoutePoint(VgMyRouteCreator::eEnd, lPlace);
    }
    // Get rid of callout.
    [self closeFrame:nil];
}

-(IBAction)toggleFrontAndBackViews:(UIButton*)sender
{
    UIView* lFromView = [mBubbleViewFront superview] ? mBubbleViewFront : mBubbleViewBack;
    UIView* lToView = [mBubbleViewFront superview] ? mBubbleViewBack : mBubbleViewFront;
    
    CFTimeInterval lDuration = 0.5;
    
    NSString* lVersion = [UIDevice currentDevice].systemVersion;
    if ( [lVersion hasPrefix:@"3."])
    {
        UIViewAnimationTransition lOptions = UIViewAnimationTransitionFlipFromLeft;
        if (lToView == mBubbleViewFront) 
        {
            lOptions = UIViewAnimationTransitionFlipFromRight;
        }
        
        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:lDuration];
        [UIView setAnimationTransition:lOptions forView:mBubbleViewContainer cache:YES];
        
        [lFromView removeFromSuperview]; 
        [mBubbleViewContainer addSubview:lToView];
        
        [UIView commitAnimations];
    }
#ifdef __IPHONE_4_0
    else
    {
        
        UIViewAnimationOptions lOptions = UIViewAnimationOptionTransitionFlipFromLeft;
        if (lToView == mBubbleViewFront) 
        {
            lOptions = UIViewAnimationOptionTransitionFlipFromRight;
        }
        
        [UIView transitionWithView:mBubbleViewContainer
                          duration:lDuration
                           options:lOptions
                        animations:^{ [lFromView removeFromSuperview]; [mBubbleViewContainer addSubview:lToView]; }
                        completion:NULL];
    }
#endif // __IPHONE_4.0    
}



-(void)loadInfoView
{
    const unsigned int cCornerRadius = 5;
    
    // Create HTML string
    std::string htmlString = "<html><head><style type='text/css'> ";
    htmlString += "body { background-color:white; color:gray; font-family:Arial, Helvetica, sans-serif;} ";
    htmlString += "h1 { font-size:22px; color:black;} ";
    htmlString += ".indented { padding-left: 5; padding-right: 5; }";
    htmlString += "</style></head><body><P>";
    htmlString += "<h1 CLASS='indented'>%s</h1>";
    htmlString += "<P CLASS='indented'>%s</P>";
    htmlString += "<P CLASS='indented'>%s</P>";
    htmlString += "<HR>" ;
    htmlString += "<P CLASS='indented'>%s</P><P><BR></P>";
    htmlString += "</body></html>";
    
    
    NSString* MyHtmlString = [NSString stringWithCString: htmlString.c_str() encoding : NSUTF8StringEncoding];
    NSString* lMyHTML = [[NSString alloc] initWithFormat:MyHtmlString, "Place information here", "", "", ""];
    
    // Load image in UIWebView
    mInfoWebView.scalesPageToFit = NO;
    [mInfoWebView loadHTMLString:lMyHTML baseURL:nil];
    
    
    NSArray* lViews = [mInfoWebView subviews];
    for ( UIView* v in lViews )
    {
        v.layer.cornerRadius = cCornerRadius;
    }
    
    mInfoWebView.layer.cornerRadius = cCornerRadius;
}

-(void) dealloc
{
    
    [self clearCallback];
    
    self.mLabelBack = nil;
    self.mLabelFront = nil;
    
    self.mPlaceID = nil;
    
    self.mRouteStartButton = nil;
    self.mRouteEndButton = nil;
    
    self.mButtonLeft = nil;
    self.mButtonRight = nil;
    
    // Various views loaded from nib files
    self.mInfoWebView = nil;
    self.mBubbleViewFront = nil;
    self.mBubbleViewBack = nil;
    self.mBubbleViewContainer = nil;

    [super dealloc];
}

@end

./Common/Src/Apple/VgMyFloorSliderView.mm

/*
 * Copyright 2011, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */
#import "VgMyFloorSliderView.h"
#import <QuartzCore/QuartzCore.h>
#include "VgMyLayerAndCameraHandler.h"

// Interface for hidden methods
@interface VgMyFloorSliderView (hidden)
-(void) sliderSetup;
-(void) sliderLabelsUpdate;
-(void) sliderThumbUpdate;
-(UILabel*) createSliderLabel:(NSInteger) pFloorIndex;
@end


@implementation VgMyFloorSliderView

@synthesize floorSlider;
@synthesize currentFloorIndex;
@synthesize numberOfFloors;
@synthesize floorLabel;
@synthesize floorThumbImage;
@synthesize labelFontSize;
@synthesize labelCentersHeights;


#define FLOOR_LABEL_TAG_OFFSET 100

- (id)initWithFrame:(CGRect)frame
        andLayerCameraHandler:(VgMyLayerAndCameraHandler*)pFloorSliderViewDelegate
{
    // Calculate the appropriate width and height for floor slider, based on 
    // parent's frame
    CGFloat lWidth = MAX(frame.size.width / 12, 50);
    CGFloat lHeight = frame.size.height / 3;
    CGRect lRect = CGRectMake(frame.size.width - (lWidth + (lWidth / 3)), 
                              frame.size.height / 3, lWidth, lHeight);
    
    self = [super initWithFrame:lRect];
    if (self) 
    {
        delegate = pFloorSliderViewDelegate;
        NSArray* lNibArray = [[NSBundle mainBundle] loadNibNamed:@"VgMyFloorSliderView" owner:self options:nil];
        for ( UIView* lView in lNibArray )
        {
            [self addSubview : lView];
        }
        [self sliderSetup];
        
        self.currentFloorIndex = 0;

        // If you want to be able to click on the slider
        UITapGestureRecognizer* lTapGesture = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)] autorelease];
        [self.floorSlider addGestureRecognizer:lTapGesture];        
    }
    return self;
}
- (void)handleTap:(UITapGestureRecognizer *)sender
{
    if (sender.state == UIGestureRecognizerStateEnded)
    {         // handling code
        CGPoint locationInView = [sender locationInView:self.floorSlider];
        float touchY = locationInView.x; // the slider has been rotated
        float halfThumbHeight = floorSlider.currentThumbImage.size.height / 2.0;
        
        NSLog(@"Tapping: %f",touchY);
        
        float lFoundDistance = 99999.0f;
        bool lFound = false;
        int lFoundIndex = 0;
        
        for (int pFloorIndex = 0 ; pFloorIndex < numberOfFloors; pFloorIndex++)
        {
            NSNumber *lNumberY = [labelCentersHeights objectAtIndex:pFloorIndex];
            float lThumbCenterY = [lNumberY floatValue];
            
            
            float lDistance = fabsf(lThumbCenterY - touchY);
            // find touch inside thumb area
            if (lDistance < halfThumbHeight)
            {
                // find closest in case thumb area overlabs.
                if (lDistance < lFoundDistance)
                {
                    lFound = true;
                    lFoundIndex = numberOfFloors - pFloorIndex - 1; // touch event has different origen.
                    lFoundDistance = lDistance;
                }
            }
        }
        if (lFound)
        {
            // simulate a touch up, if we do a setCurrentFloorIndex:(int) the floor thumb will jump
            floorSlider.value = lFoundIndex;
            [self sliderTouchUp:nil];
        }
    }
}

-(void) setNumberOfFloors:(NSInteger)pNumOfFloors
{
    numberOfFloors = pNumOfFloors;
    
    
    self.labelCentersHeights = [NSMutableArray arrayWithCapacity:numberOfFloors];
    
    // IMPORTANT: Use width and height interchangably for slider values as
    // slider has been transform rotated.
    CGRect trackRect = [floorSlider trackRectForBounds:floorSlider.bounds];
    CGRect thumbRect = [floorSlider thumbRectForBounds:floorSlider.bounds
                                             trackRect:trackRect
                                                 value:floorSlider.value];
    NSInteger lThumbOffset = (thumbRect.size.width);
    CGFloat lUsableHeight = trackRect.size.width - lThumbOffset;
    NSInteger lMaxFloorIndex = std::max(numberOfFloors - 1,1);
    float lTrackOriginX = trackRect.origin.x;
    for (int pFloorIndex = 0; pFloorIndex < numberOfFloors; pFloorIndex++)
    {
        CGFloat lOriginY = ((lMaxFloorIndex - pFloorIndex) * (lUsableHeight / lMaxFloorIndex));
        CGFloat lHeightY = lOriginY + (lThumbOffset / 2) + lTrackOriginX;
        
    [labelCentersHeights insertObject:[NSNumber numberWithFloat:lHeightY] atIndex:pFloorIndex];
    }
    
    
    // If there are less then two floors, then the floor sliders isn't required.
    if (numberOfFloors < 2)
    {
        self.hidden = YES;
    }
    else
    {
        self.hidden = NO;
        [floorSlider setMaximumValue:(numberOfFloors - 1)];
        [self sliderLabelsUpdate];
    }     
}


/*
 * Overide the set function for currentFloorIndex
 */
-(void) setCurrentFloorIndex:(NSInteger)pCurrentFloor
{
    currentFloorIndex = pCurrentFloor;
    // Ensure the slider position corresponds with current floor
    [floorSlider setValue:currentFloorIndex];
    // Update the slider
    [self sliderLabelsUpdate];
    [self sliderThumbUpdate];
}


/*
 * Updates all the labels on the slider representing 
 */ 
-(void) sliderLabelsUpdate
{        
    for (int i = 0; i < numberOfFloors; i++) 
    {
        // Remove previous label before adding new one
        UILabel* lLabelToRemove = (UILabel*) [self viewWithTag:(i+FLOOR_LABEL_TAG_OFFSET)];
        if (lLabelToRemove != nil) 
        {
            [lLabelToRemove removeFromSuperview];
        }        
        
        UILabel* lLabel = [self createSliderLabel:i];
        [self addSubview:lLabel];
    }   
} 

/*
 * Update the slider thumb so it's correctly displaying the current floor and in
 * the correct position.
 */ 
-(void) sliderThumbUpdate
{
    float sliderOrigin = floorSlider.frame.origin.x + (floorSlider.currentThumbImage.size.height / 2.0);
    float sliderRange = floorSlider.frame.size.height - floorSlider.currentThumbImage.size.height;
    float sliderValueToPixels = (floorSlider.value / (floorSlider.maximumValue - floorSlider.minimumValue)) * sliderRange;
    CGPoint lThumbCenter = CGPointMake(floorSlider.center.x, sliderOrigin + (sliderRange - sliderValueToPixels));
    
    
    floorLabel.center = lThumbCenter;
    floorThumbImage.center = lThumbCenter;
    
    [self bringSubviewToFront:floorThumbImage];
    [self bringSubviewToFront:floorLabel];
    
    NSString* lCurrentFloorTitle;
    std::string lLayerName;
    if (delegate->getLayerName(roundf(floorSlider.value), lLayerName))
    {
        lCurrentFloorTitle = [NSString stringWithFormat:@"%s", lLayerName.c_str()];
    }
    else
    {
        lCurrentFloorTitle = [NSString stringWithFormat:@"%d", currentFloorIndex];
    }
    [floorLabel setText:lCurrentFloorTitle];
}


/*
 * Customise the UISlider appearance and set default start up values.
 */
-(void) sliderSetup
{
    // Note: Height and width are swapped because the slider is transform rotated.
    floorSlider.frame = CGRectMake(0, 0, self.frame.size.height, self.frame.size.width);
    floorSlider.center = CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2);
    
    // Setup the custom slider images
    {
        self.floorThumbImage = nil;
        UIImage* lThumbImageClear = [UIImage imageNamed:@"SliderThumbClear.png"];
        UIImage* lThumbImage = [UIImage imageNamed:@"SliderThumb.png"];
        // Using the stretch property has problems on iOS7. #4719
        //UIImage* lThumbTrack = [[UIImage imageNamed:@"SliderTrack.png"] stretchableImageWithLeftCapWidth: 22 topCapHeight: 0];
        UIImage* lThumbTrack = [UIImage imageNamed:@"SliderTrack.png"];
        
        // Note: the actual slider thumb will be hidden under our version of the thumb.  
        [floorSlider setThumbImage:lThumbImageClear forState:UIControlStateNormal];                        
        [floorSlider setMaximumTrackImage:lThumbTrack forState:UIControlStateNormal];
        [floorSlider setMinimumTrackImage:lThumbTrack forState:UIControlStateNormal];
        [floorSlider setMinimumValue:0.0];
        
        floorThumbImage = [[UIImageView alloc] initWithImage:lThumbImage];
        [self addSubview:floorThumbImage];
    }    
    
    // Create the basic set up for the floor label which will appear over the 
    // thumb slider.
    {
        self.floorLabel = nil;
        // Add a space betwewen the label bounds and the buffer image.
        CGRect lFloorLabelFrame = CGRectMake(0, 0, floorThumbImage.frame.size.width - 8, floorThumbImage.frame.size.height - 8);
        floorLabel = [[UILabel alloc] initWithFrame:lFloorLabelFrame];
        [self addSubview:floorLabel];
        // not using self.labelFontSize, since we made this variable read-only
        labelFontSize = (floorThumbImage.frame.size.width / 2);        
        [floorLabel setBackgroundColor:[UIColor clearColor]];
        [floorLabel setTextColor:[UIColor whiteColor]];
        [floorLabel setFont:[UIFont boldSystemFontOfSize:labelFontSize]];
        [floorLabel setTextAlignment:UITextAlignmentCenter];
    }
    
    // Verticalize the slider, making the Min value to the bottom
    {
        CGAffineTransform trans = CGAffineTransformMakeRotation(M_PI * -0.5);
        floorSlider.transform = trans;
    }
}

/* 
 * Enables autoshrinking of text labels.
 */
-(void)enableAutoShrinkFactor:(BOOL)pFlag withScale:(double)pScale
{
    if (pFlag)
    {
        // adjust labels to handle datasets like DubaiMall.
        floorLabel.adjustsFontSizeToFitWidth = YES;
        floorLabel.numberOfLines = 1;
        if ([floorLabel respondsToSelector:@selector(setMinimumFontSize:)])
        {
            // pre iOS6, still seems to work in iOS6
            floorLabel.minimumFontSize = self.labelFontSize * pScale ;
        }
    } else {
        floorLabel.adjustsFontSizeToFitWidth = NO;
        
    }
}

/*
 * Creates a label that can be placed on the slider bar which will represent 
 * the floor, indicated by pFloorIndex.
 */
-(UILabel*)createSliderLabel:(NSInteger) pFloorIndex
{
    UILabel* lFloorLabel = nil;
    
    if (0 != numberOfFloors &&
        pFloorIndex < numberOfFloors) 
    {
        // IMPORTANT: Use width and height interchangably for slider values as 
        // slider has been transform rotated.
        CGRect trackRect = [floorSlider trackRectForBounds:floorSlider.bounds];
        CGRect thumbRect = [floorSlider thumbRectForBounds:floorSlider.bounds 
                                                 trackRect:trackRect
                                                     value:floorSlider.value];
        
        // Default setup for inactive label.
        UIColor* lBackgroundColor = [UIColor colorWithRed:0.6875 green:0.0 blue:0.0 alpha:1];
        UIColor* lTextColor = [UIColor blackColor];
        CGFloat lLabelHeight = thumbRect.size.width / 4;
        CGFloat lLabelWidth = thumbRect.size.height - (thumbRect.size.height / 3);
        CGFloat lLabelCornerRadius = lLabelHeight / 2;        
        UIColor* lBackgroundBorderColor = [UIColor clearColor];
        CGFloat lBackgroundBorderWidth = 0;
        
        // Configure for the label representing current floor
        if(pFloorIndex == currentFloorIndex)
        {
            // Possible to configure the label representing current floor a 
            // little differently if desired.
        }
        
        lFloorLabel = [[[UILabel alloc]initWithFrame:CGRectMake(0, 0, lLabelWidth, lLabelHeight)] autorelease];

        NSNumber *lNumberY = [labelCentersHeights objectAtIndex:pFloorIndex];
        CGFloat lY = [lNumberY floatValue];
        lFloorLabel.center = CGPointMake(floorSlider.center.x, lY);
        
        // Add tag for removing labels later.
        lFloorLabel.tag = pFloorIndex + FLOOR_LABEL_TAG_OFFSET; 
        [lFloorLabel setTextAlignment:UITextAlignmentCenter];
        [lFloorLabel setTextColor:lTextColor];
        [lFloorLabel setBackgroundColor:lBackgroundColor];
        lFloorLabel.layer.cornerRadius = lLabelCornerRadius;
        lFloorLabel.layer.borderWidth = lBackgroundBorderWidth;
        lFloorLabel.layer.borderColor = lBackgroundBorderColor.CGColor;   
    }
    return lFloorLabel;
}

#pragma mark - UIControl touch event tracking

-(IBAction)sliderValueChanged:(id)sender 
{
    [self sliderThumbUpdate];   
}


-(IBAction)sliderTouchUp:(id)sender
{
    int lNewFloor = roundf(floorSlider.value);
    floorSlider.value = lNewFloor;
    if (currentFloorIndex != lNewFloor) 
    {
        self.currentFloorIndex = lNewFloor;
        if (delegate)
        {
            delegate->gotoLayer(lNewFloor);
        }
    }
    [self sliderThumbUpdate];
}

- (void)dealloc 
{
    self.floorSlider = nil;
    self.floorLabel = nil;
    self.floorThumbImage = nil;
    self.labelCentersHeights = nil;
    
    [super dealloc];
}

@end

./Common/Src/Apple/VgMyInstructionView.mm

/*
 * Copyright 2011, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

#import <QuartzCore/QuartzCore.h>
#import "VgMyInstructionView.h"

#include "VgApplication/VgIApplication.h"
#include "VgApplication/VgIModuleManager.h"

#include "VgEngine/VgIEngine.h"
#include "VgEngine/VgICamera.h"
#include "VgEngine/VgPositionToolbox.h"

#include "Modules/Map/VgIMapModule.h"
#include "Modules/Map/VgPlaceColorDescriptor.h"
#include "Modules/Navigation/VgINavigationModule.h"
#include "Modules/Navigation/VgINavigation.h"

#include "VgMyInstructionUpdateListener.h"
#include "VgMyNavigationHelper.h"

#define INSTRUCTION_VIEW_BORDER_WIDTH 1

@implementation VgMyInstructionView

@synthesize mInstructionLabel;
@synthesize mInstructionLabelDetail;
@synthesize mDistance;
@synthesize mXofYLabel;
@synthesize mInstructionView;
@synthesize mInstructionManeuverType;
@synthesize mNextInstruction;
@synthesize mPrevInstruction;



-(id) initWithFrame:(CGRect)frame withApplication:(VgApplication::VgIApplication*)pVgApplication withUpdateListener:(VgMyInstructionUpdateListener *)pUpdateListener
{
    if ((self = [super initWithFrame:frame]))
    {
        mIsIPad = NO;
        
#ifdef __IPHONE_3_2
        //        // we know we are in new SDK
        if ( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad )
        {
            mIsIPad = YES;
        }
#endif // __IPHONE_3_2  
        
        // Initialization code
        NSString* lInstructionViewXibName = @"VgMyInstructionView";
        if ( mIsIPad )
        {
            lInstructionViewXibName = @"VgMyInstructionView~iPad";
        }
        
        [[NSBundle mainBundle] loadNibNamed : lInstructionViewXibName owner : self options : nil];
        
        CGRect lNewFrame = CGRectMake(-(INSTRUCTION_VIEW_BORDER_WIDTH), 0, (frame.size.width + (2 * INSTRUCTION_VIEW_BORDER_WIDTH)), HEIGHT_INSTRUCTION_VIEW);
        mInstructionView.frame = lNewFrame;
        self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin;
        
        [self addSubview : mInstructionView];
        
        mVgApplication = pVgApplication;
        mMapModule = (VgMapModule::VgIMapModule*)mVgApplication->editModuleManager()->queryModule("Map");
        mUpdateListener = pUpdateListener;
        
        NSArray* lLangArray = [NSLocale preferredLanguages];
        std::string lLocaleString = "en";
        if ([lLangArray count] > 0)
        {
           lLocaleString  = [[lLangArray objectAtIndex:0] UTF8String];
            
        }
        
        // force french to test
        //lLocaleString = "fr";
        mCurrentLocaleTranslateID = VgMyNavigationHelper::getLangId(lLocaleString);
        
#ifdef __IPHONE_3_2
        NSString* lVersion = [UIDevice currentDevice].systemVersion;
        if ( [lVersion hasPrefix:@"3.0"] || [lVersion hasPrefix:@"3.1"] )
        {
        }
        else 
        {
            // iOS 3.2 and later
            mInstructionView.layer.shadowColor = [UIColor blackColor].CGColor;
            mInstructionView.layer.shadowOffset = CGSizeMake(0, 5);
            mInstructionView.layer.shadowOpacity = 0.5;
        }
#endif
        mInstructionView.layer.borderWidth = INSTRUCTION_VIEW_BORDER_WIDTH;
        mInstructionView.layer.borderColor = [UIColor whiteColor].CGColor;
        
        
        UIDevice* lDevice = [UIDevice currentDevice];
        int lMajorVersion = [[[lDevice.systemVersion componentsSeparatedByString:@"."] objectAtIndex:0] intValue];
        if (lMajorVersion >= 7)
        {
            // on iOS7 the view happens to be above the status bar, which is transparent.  In that case
            // we move the text down some. (#4719)
            CGRect lLabelFrame = self.mInstructionLabel.frame;
            lLabelFrame.origin.y += 13;
            self.mInstructionLabel.frame = lLabelFrame;
            
            CGRect lLabelDetailedFrame = self.mInstructionLabelDetail.frame;
            lLabelDetailedFrame.origin.y += 12;
            lLabelDetailedFrame.size.height -= 3;
            self.mInstructionLabelDetail.frame = lLabelDetailedFrame;
        }
        
    }
    
    return self;
}

/*
 * Set the navigation instruction.
 * The text for the instruction is computed here.
 */
-(void) setInstruction:(VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigationInstruction > &) pNavigationInstruction withNavigation:(VgEngine::VgConstRefPtr<  VgNavigationModule::VgINavigation >const&)pNavigation

{
    mInstruction = pNavigationInstruction;
    // apper if it was not visible.
    self.hidden = NO;
    
    //VgNavigationModule::VgManeuverType lManeuverType = pNavigationInstruction->getManeuverType();
    
    // Set instruction content
    //int lInstructionIndex = pNavigationInstruction->getIndex();
    std::string lDetail;
    
    VgMyNavigationHelper::VgTranslatedInstruction lTranslatedInstruction;
    VgMyNavigationHelper::translateInstruction(pNavigationInstruction, pNavigation, lTranslatedInstruction, *mMapModule,   mCurrentLocaleTranslateID);
    NSString* lInstructionDetail;
    const unsigned int lTotalNumberOfInstructions = pNavigation->getNumInstructions();
    lDetail = lTranslatedInstruction.mMessage;
    
    NSStringEncoding lStringEncoding = NSUTF8StringEncoding;
    
    NSString* lInstruction = [NSString stringWithCString:lTranslatedInstruction.mBrief.c_str() encoding:lStringEncoding];
    [mInstructionLabel setText: lInstruction];
    
    NSString* lWalkingTimeInMinutesStr = [NSString stringWithCString:lTranslatedInstruction.mDuration.c_str() encoding:lStringEncoding];

    
    /*
     * Update instruction on instruction view.
     */
    lInstructionDetail  = [NSString stringWithCString:lDetail.c_str() encoding:lStringEncoding];
    [mInstructionLabelDetail setText: lInstructionDetail];
    
    [mXofYLabel setText :[NSString stringWithFormat : @"%d/%d", pNavigationInstruction->getIndex()+1, lTotalNumberOfInstructions]];
    
    // mDistance uses time.
    [mDistance setText:lWalkingTimeInMinutesStr];
    
    [self updateManeuverWithType : pNavigationInstruction->getManeuverType()];
    // Update the next and previous buttons.
    {
        [mPrevInstruction setEnabled:YES];
        [mNextInstruction setEnabled:YES];
        
        unsigned int lInstructionIndex = pNavigationInstruction->getIndex();
        
        if (lInstructionIndex == 0) 
        {
            [mPrevInstruction setEnabled:NO];
        }
        else if (lInstructionIndex == (lTotalNumberOfInstructions - 1))
        {
            [mNextInstruction setEnabled:NO];
        }
    }
}

-(void) updateManeuverWithType:(unsigned int)maneuverType
{
    NSString* lImageName = nil;
    
    switch ( maneuverType )
    {
        case VgNavigationModule::eVgManeuverTypeUnknown:
            lImageName = nil;
            break;
        case VgNavigationModule::eVgManeuverTypeGoStraight:
            lImageName = @"transit_instruction_straight.png";
            break;
        case VgNavigationModule::eVgManeuverTypeTurnGentleRight:
            lImageName = @"transit_instruction_turn_gentle_right.png";
            break;
        case VgNavigationModule::eVgManeuverTypeTurnGentleLeft:
            lImageName = @"transit_instruction_turn_gentle_left.png";
            break;
        case VgNavigationModule::eVgManeuverTypeTurnRight:
            lImageName = @"transit_instruction_turn_right.png";
            break;
        case VgNavigationModule::eVgManeuverTypeTurnLeft:
            lImageName = @"transit_instruction_turn_left.png";
            break;
        case VgNavigationModule::eVgManeuverTypeTurnSharpRight:
            lImageName = @"transit_instruction_turn_sharp_right.png";
            break;
        case VgNavigationModule::eVgManeuverTypeTurnSharpLeft:
            lImageName = @"transit_instruction_turn_sharp_left.png";
            break;
        case VgNavigationModule::eVgManeuverTypeUTurnLeft:
            lImageName = @"transit_instruction_uturn_left.png";
            break;
        case VgNavigationModule::eVgManeuverTypeUTurnRight:
            lImageName = @"transit_instruction_uturn_right.png";
            break;
        case VgNavigationModule::eVgManeuverTypeStart:
            lImageName = @"transit_instruction_start.png";
            break;
        case VgNavigationModule::eVgManeuverTypeEnd:
            lImageName = @"transit_instruction_end.png";
            break;
        case VgNavigationModule::eVgManeuverTypeGoUp:
            lImageName = @"transit_instruction_stairs_up.png";
            break;
        case VgNavigationModule::eVgManeuverTypeGoDown:
            lImageName = @"transit_instruction_stairs_down.png";
            break;
        default:
            break;
    }
    
    UIImage* lImage = [UIImage imageNamed:lImageName];
    [mInstructionManeuverType setImage : lImage];
}

-(IBAction) nextInstruction:(id)sender
{
    if (mInstruction.isValid())
    {
        mUpdateListener->goToInstruction(mInstruction->getIndex() + 1);
    }
}

-(IBAction) prevInstruction:(id)sender
{
    if (mInstruction.isValid())
    {
        mUpdateListener->goToInstruction(mInstruction->getIndex() - 1);
    }
}

-(IBAction) clearRoute:(id)sender
{
    // Not implemented in the example.
}


// NOT USED
-(void) notifyPositionUpdated: (VgEngine::VgConstRefPtr<  VgNavigationModule::VgINavigation >const&)pNavigation withPosition:(const VgEngine::VgPosition&) pPosition withTime:(double) pTime
{
    if (pNavigation.isValid())
    {
        return;
    }
    
    unsigned int lInstructionIndex = pNavigation->getCurrentInstructionIndex();
    // we don't update for the last instruction
    if (lInstructionIndex < (pNavigation->getNumInstructions() - 1))
    {
        const VgEngine::VgPosition& lPositionOnRoute = pNavigation->getClosestPositionOnRoute();
        const VgEngine::VgPosition& lPositionNextInstruction = pNavigation->getInstruction(lInstructionIndex+1)->getPosition();
        
        const double lDistance = mVgApplication->editEngine()->getPositionToolbox()->computeDistance(lPositionOnRoute,lPositionNextInstruction);
        
        // Display remaining distance
        [mDistance setText:[NSString stringWithFormat : @"%2.0f out of %2.0f m",lDistance, pNavigation->getInstruction(lInstructionIndex)->getLength()]];
    }
}

// NOT USED
-(void) notifyNewInstruction: (VgEngine::VgConstRefPtr<  VgNavigationModule::VgINavigation >const&)pNavigation withIndex:(unsigned int) pIndex
{
    VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigationInstruction > lInstruction = pNavigation->getInstruction(pIndex);
    [self setInstruction:lInstruction withNavigation:pNavigation];
}


-(void) dealloc
{
    [mInstructionLabel release];
    [mInstructionLabelDetail release];
    [mDistance release];
    [mXofYLabel release];
    [mInstructionView release];
    [mInstructionManeuverType release];
    [mNextInstruction release];
    [mPrevInstruction release];
    
    [super dealloc];
}

@end

./Common/Src/Apple/VgMyMapPlaceListenerWithBubble.mm

/*
 * Copyright 2011, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

#import "VgMyMapPlaceListenerWithBubble.h"
#include "VgEngine/VgICamera.h"
#include "VgEngine/VgIEngine.h"
#import "Apple/VgEAGLView.h"
#include "VgEngine/VgTypes.h"

#include "VgApplication/VgIApplication.h"
#include "VgApplication/VgIModuleManager.h"
#include "Modules/Map/VgIMapModule.h"
#include "Modules/Map/VgPlaceDescriptor.h"

#import "VgMyBubbleView.h"
#include "VgMyRouteCreator.h"

#include "VgMyLayerAndCameraHandler.h"


// This is a C++ class, but is it coded in a .mm file so it can call objective C functions related to
// the bubble view.

VgMyMapPlaceListenerWithBubble::VgMyMapPlaceListenerWithBubble(VgEAGLView* pVgEAGLView, VgMyRouteCreator* pRouteCreator)
    : mVgEAGLView(pVgEAGLView)
    , mCurrentCallout(nil)
    , mRouteCreator(pRouteCreator)
{
    VgApplication::VgIApplication* lVgApplication = [mVgEAGLView getApplication];
    
    mMapModule = static_cast< VgMapModule::VgIMapModule* >(lVgApplication->editModuleManager()->queryModule("Map"));
    
    mMapModule->addListener(this);
}

VgMyMapPlaceListenerWithBubble::~VgMyMapPlaceListenerWithBubble()
{
    hideBubble();
    if(mCurrentCallout)
    {
        // in C++ member variable mCurrentCallout does not have properties.
        // the first release is for the retain we did at creation
        // the second release is to trigger the deallocation.
        [mCurrentCallout release];
        mCurrentCallout = nil;
    }
}

void VgMyMapPlaceListenerWithBubble::notifyPlaceSelected (VgApplication::VgIApplication& pVgApplication, const std::string& pID, const VgEngine::VgPosition& pPosition)
{
    VgMapModule::VgIMapModule* lMapModule = (VgMapModule::VgIMapModule*)pVgApplication.editModuleManager()->queryModule("Map");

    if ( lMapModule == NULL )
    {
        // License unavailable for the MapModule.
        return;
    }

    // Prepare placename
    std::string lPlaceName;
    lMapModule->getPlaceName(pID, lPlaceName);
    std::string lMsg = pID + "/" + lPlaceName;
    
    VgMapModule::VgPlaceDescriptor lPlaceDescriptor;
    lMapModule->queryPlaceDescriptor(pID, lPlaceDescriptor);
    mCurrentAnchoredLayer = lPlaceDescriptor.mLayerName;
    
    hideBubble();
    
    // Release the memory here because otherwise there is a chance that the bubble view
    // will be released while it's in the process of requesting a route.
    if(mCurrentCallout)
    {
        // in C++ member variable mCurrentCallout does not have properties.
        // the first release is for the retain we did at creation
        // the second release is to trigger the deallocation.
        [mCurrentCallout release];
        mCurrentCallout = nil;
    }
    
    bool lIsRoutingEnabled = (pVgApplication.editModuleManager()->queryModule("Routing") != NULL);
    
    mCurrentCallout = [[VgMyBubbleView alloc] initWithEngine:pVgApplication.editEngine() 
                                                  position:pPosition 
                                                    withID:pID
                                                   withRouting:lIsRoutingEnabled
                                            withRouteCreator:mRouteCreator];
    // since we are in C++ class, we cannot add a property to the member variable
    // thus, we need to retain mCurrentCallout manually.
    
    showBubble(pPosition, pID, lMsg);
}

void VgMyMapPlaceListenerWithBubble::hideBubble ()
{
    [mCurrentCallout removeFromSuperview];
}

void VgMyMapPlaceListenerWithBubble::showBubble (const VgEngine::VgPosition& pPosition, const std::string& pID, const std::string& pMessage)
{
    [mVgEAGLView addSubview:mCurrentCallout];
}

void VgMyMapPlaceListenerWithBubble::layerWillChangeFrom(VgMyLayerAndCameraHandler* pSender, const std::string& pFloorFrom, const std::string& pFloorTo)
{
    if (!pSender->isGlobalView())
    {
        hideBubble();   // No matter the transition, in detailed view mode, the bubble is hidden.
    }
}

void VgMyMapPlaceListenerWithBubble::layerChangedTo(VgMyLayerAndCameraHandler* pSender, const std::string& pFloorFrom, const std::string& pFloorTo)
{
    if (!pSender->isGlobalView())
    {
        hideBubble();   // No matter the transition, in detailed view mode, the bubble is hidden.
    }
}

void VgMyMapPlaceListenerWithBubble::viewWillChange(VgMyLayerAndCameraHandler* pSender, const bool pDoesChangeFromGlobalToDetailed)
{
    if (pDoesChangeFromGlobalToDetailed && pSender->getFocusedLayerName() != mCurrentAnchoredLayer)
    {
        hideBubble();
    }
    // leaving detailed view
    if (!pDoesChangeFromGlobalToDetailed)
    {
        mMapModule->removeListener(this);
    }
}
void VgMyMapPlaceListenerWithBubble::viewDidChange(VgMyLayerAndCameraHandler* pSender, const bool pDoesChangeFromGlobalToDetailed)
{
    // arriving at detailed view
    if (pDoesChangeFromGlobalToDetailed)
    {
        mMapModule->addListener(this);
    }
}

./Common/Src/Qt/VgQtInstructionWidget.cpp

/*
* Copyright 2012, Visioglobe SAS
* ALL RIGHTS RESERVED
*
*
* LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
* distribute, and create derivative works from this Source Code,
* provided that: (1) the user reproduces this entire notice within
* both source and binary format redistributions and any accompanying
* materials such as documentation in printed or electronic format;
* (2) the Source Code is not to be used, or ported or modified for
* use, except in conjunction with Visioglobe SDK; and (3) the
* names of Visioglobe SAS may not be used in any
* advertising or publicity relating to the Source Code without the
* prior written permission of Visioglobe.  No further license or permission
* may be inferred or deemed or construed to exist with regard to the
* Source Code or the code base of which it forms a part. All rights
* not expressly granted are reserved.
*
* This Source Code is provided to Licensee AS IS, without any
* warranty of any kind, either express, implied, or statutory,
* including, but not limited to, any warranty that the Source Code
* will conform to specifications, any implied warranties of
* merchantability, fitness for a particular purpose, and freedom
* from infringement, and any warranty that the documentation will
* conform to the program, or any warranty that the Source Code will
* be error free.
*
* IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
* LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
* ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
* SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
* OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
* PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
* OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
* USE, THE SOURCE CODE.
*
* Contact information:  Visioglobe SAS,
* 300, avenue des papeteries,
* 38190 Villard-Bonnot
* FRANCE
* or:  http://www.visioglobe.com
*/

#include <QtCore/QLocale> 

#include "VgQtInstructionWidget.hxx"

#include "Modules/Map/VgIMapModule.h"

#include "Modules/Navigation/VgINavigation.h"
#include "Modules/Navigation/VgINavigationModule.h"
#include "Modules/Navigation/VgINavigationInstruction.h"

#include "VgMyInstructionUpdateListener.h"
#include "VgMyNavigationHelper.h"

#include <set>
#include <math.h>

VgQtInstructionWidget::VgQtInstructionWidget(VgMapModule::VgIMapModule* pMapModule, VgMyInstructionUpdateListener* pUpdateListener, QWidget* pParent)
: QWidget(pParent)
, mInstruction(NULL)
, mUpdateListener(pUpdateListener)
, mMapModule(pMapModule)
{
    setupUi(this);
}

VgQtInstructionWidget::~VgQtInstructionWidget()
{}

void VgQtInstructionWidget::updateWithInstruction(VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigation > const& pNavigation, unsigned int pIndex)
{
    // Get instruction content
    mInstruction = pNavigation->getInstruction(pIndex);
    VgMyNavigationHelper::VgTranslatedInstruction lTranslated;



    // format systems language
    QString defaultLocale = QLocale::system().name();       // e.g. "de_DE"
    defaultLocale.truncate(defaultLocale.lastIndexOf('_')); // e.g. "de"
    char *lVisioglobeLang = "en";
    // VisioDevKit currently only supports instructions in French and English.
    if (defaultLocale == QString("fr"))
    {
        lVisioglobeLang = "fr";
    }
    int lLang = VgMyNavigationHelper::getLangId(lVisioglobeLang);

    if (lLang < 0)
    {
        // This is an error, issue a message, dialog, ...
        // Language index 0 is always valid
        lLang = 0;
    }
    VgMyNavigationHelper::translateInstruction(mInstruction, pNavigation, lTranslated, *mMapModule, lLang);

    // Update instruction on instruction view.
    mInstructionTitle->setText(QString::fromUtf8(lTranslated.mBrief.c_str()));
    mInstructionLabel->setText(QString::fromUtf8(lTranslated.mMessage.c_str()));
    mLengthLabel->setText(QString("%1").arg(mInstruction->getLength()));
    mDurationLabel->setText(QString("%1").arg(mInstruction->getDuration()));
    mETALabel->setText(QString("%1").arg(mInstruction->getETA()));
    mTimeLabel->setText(QString("%1").arg(mInstruction->getTime()));
    QString lString;
    std::set< std::string >::const_iterator lIter;
    for (lIter = mInstruction->getAttributes().begin(); lIter != mInstruction->getAttributes().end(); ++lIter)
    {
        if (lIter != mInstruction->getAttributes().begin())
        {
            lString += " " ;
        }
        lString += "[" + QString::fromUtf8(lIter->c_str()) + "]";
    }
    mAttributesLabel->setText(lString);
}


void VgQtInstructionWidget::show()
{
    QWidget::show();
}


void VgQtInstructionWidget::hide()
{
    QWidget::hide();
}


bool VgQtInstructionWidget::isVisible()
{
    return QWidget::isVisible();
}

void VgQtInstructionWidget::on_mPreviousInstructionButton_clicked()
{
    if (mInstruction)
    {   
        mUpdateListener->goToInstruction(mInstruction->getIndex() - 1);
    }
}

// AUTO-CONNECT syntax
void VgQtInstructionWidget::on_mNextInstructionButton_clicked()
{
    if (mInstruction)
    {
        mUpdateListener->goToInstruction(mInstruction->getIndex() + 1);
    }

}


void VgQtInstructionWidget::clear()
{
    this->hide();
}

./Common/Src/Qt/VgQtPlaceWidget.cpp

./Common/Src/Qt/VgQtRoutingDisplayWidget.cpp

/*
* Copyright 2012, Visioglobe SAS
* ALL RIGHTS RESERVED
*
*
* LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
* distribute, and create derivative works from this Source Code,
* provided that: (1) the user reproduces this entire notice within
* both source and binary format redistributions and any accompanying
* materials such as documentation in printed or electronic format;
* (2) the Source Code is not to be used, or ported or modified for
* use, except in conjunction with Visioglobe SDK; and (3) the
* names of Visioglobe SAS may not be used in any
* advertising or publicity relating to the Source Code without the
* prior written permission of Visioglobe.  No further license or permission
* may be inferred or deemed or construed to exist with regard to the
* Source Code or the code base of which it forms a part. All rights
* not expressly granted are reserved.
*
* This Source Code is provided to Licensee AS IS, without any
* warranty of any kind, either express, implied, or statutory,
* including, but not limited to, any warranty that the Source Code
* will conform to specifications, any implied warranties of
* merchantability, fitness for a particular purpose, and freedom
* from infringement, and any warranty that the documentation will
* conform to the program, or any warranty that the Source Code will
* be error free.
*
* IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
* LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
* ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
* SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
* OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
* PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
* OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
* USE, THE SOURCE CODE.
*
* Contact information:  Visioglobe SAS,
* 300, avenue des papeteries,
* 38190 Villard-Bonnot
* FRANCE
* or:  http://www.visioglobe.com
*/

#include "VgQtRoutingDisplayWidget.hxx"

#include "Modules/Routing/VgIRoute.h"

VgQtRoutingDisplayWidget::VgQtRoutingDisplayWidget(VgMyRouteDisplay* pRouteDisplay, QWidget* pParent)
: QWidget(pParent)
, mRouteDisplay(pRouteDisplay)
{
    setupUi(this);
}


VgQtRoutingDisplayWidget::~VgQtRoutingDisplayWidget()
{}


bool VgQtRoutingDisplayWidget::createRouteObjects(VgEngine::VgConstRefPtr< VgRoutingModule::VgIRoute > const& pRoute)
{
    QWidget::show();
    return mRouteDisplay->createRouteObjects(pRoute);
}


void VgQtRoutingDisplayWidget::clear()
{
    mRouteDisplay->clear();
    QWidget::hide();
}


void VgQtRoutingDisplayWidget::show()
{

    mRouteDisplay->show();
}


void VgQtRoutingDisplayWidget::hide()
{
    mRouteDisplay->hide();
}


bool VgQtRoutingDisplayWidget::isVisible()
{
    return mRouteDisplay->isVisible();
}

void VgQtRoutingDisplayWidget::on_mShowButton_clicked()
{
    this->show();
}

// AUTO-CONNECT syntax
void VgQtRoutingDisplayWidget::on_mHideButton_clicked()
{
    this->hide();
}

// AUTO-CONNECT syntax
void VgQtRoutingDisplayWidget::on_mClearButton_clicked()
{
    this->clear();
    emit onClearRoute();
}

./Common/Src/Qt/VgQtWidget.cpp

/*
* Copyright 2012, Visioglobe SAS
* ALL RIGHTS RESERVED
*
*
* LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
* distribute, and create derivative works from this Source Code,
* provided that: (1) the user reproduces this entire notice within
* both source and binary format redistributions and any accompanying
* materials such as documentation in printed or electronic format;
* (2) the Source Code is not to be used, or ported or modified for
* use, except in conjunction with Visioglobe SDK; and (3) the
* names of Visioglobe SAS may not be used in any
* advertising or publicity relating to the Source Code without the
* prior written permission of Visioglobe.  No further license or permission
* may be inferred or deemed or construed to exist with regard to the
* Source Code or the code base of which it forms a part. All rights
* not expressly granted are reserved.
*
* This Source Code is provided to Licensee AS IS, without any
* warranty of any kind, either express, implied, or statutory,
* including, but not limited to, any warranty that the Source Code
* will conform to specifications, any implied warranties of
* merchantability, fitness for a particular purpose, and freedom
* from infringement, and any warranty that the documentation will
* conform to the program, or any warranty that the Source Code will
* be error free.
*
* IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
* LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
* ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
* SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
* OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
* PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
* OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
* USE, THE SOURCE CODE.
*
* Contact information:  Visioglobe SAS,
* 300, avenue des papeteries,
* 38190 Villard-Bonnot
* FRANCE
* or:  http://www.visioglobe.com
*/
#include "Qt/Moc/VgQtWidget.hxx"

#include <QtGui/QGraphicsScene>
#include <QtOpenGL/QtOpenGL>

#include "Qt/Moc/QtVisioSample.hxx"
#include "Qt/VgQtGraphicsView.hxx"
#include "Qt/VgQtScene.hxx"

#include "VgMyStackedLayerAndCameraHandler.h"

const int cTimePerFrame = 16;

static bool mRenderOnDemand = false;

VgQtWidget::VgQtWidget (QWidget* pParent, Qt::WindowFlags pFlags)
: QWidget(pParent, pFlags)
, mVgScene(NULL)
, mVgGraphicsView(NULL)
{
    if ( !QGLFormat::hasOpenGL() || !QGLFramebufferObject::hasOpenGLFramebufferObjects())
    {
        QMessageBox::information(0, "OpenGL framebuffer objects",
            "This system does not support OpenGL/framebuffer objects.");
    }

    QGLFormat lFormat(QGL::SampleBuffers | QGL::DoubleBuffer | QGL::DirectRendering);
    // For buggy drivers (like ATI or Intel EAGD) we want to disable swapInterval.
    lFormat.setSwapInterval(0);
    lFormat.setSampleBuffers(true);
    lFormat.setSamples(4);

    // Initializes the OpenGL widget that will render the QGraphicsScene
    QGLWidget *lGLWidget = new QGLWidget(lFormat);
    lGLWidget->makeCurrent();

    mVgScene = new VgQtScene(300, 300, mRenderOnDemand, cTimePerFrame, NULL);

    // Installs an event filter on the scene to capture and handle the event we want.
    connect(mVgScene, SIGNAL(VgSizeChanged(QResizeEvent*)), this, SLOT(handleVgSizeChanged(QResizeEvent*)));
    
    // Creates the QGraphicsView widget that will draw in background the QGLWidget and its scene.
    mVgGraphicsView = new VgQtGraphicsView(this);
    mVgGraphicsView->setViewport(lGLWidget);
    mVgGraphicsView->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
    mVgGraphicsView->setScene(mVgScene);

    mVgGraphicsView->viewport()->setAttribute(Qt::WA_AcceptTouchEvents);
    mVgGraphicsView->setAttribute(Qt::WA_AcceptTouchEvents);

    connect(mVgGraphicsView, SIGNAL(onPostResizeScene(QResizeEvent*)), mVgScene, SLOT(handleResizeEvent(QResizeEvent*)));

    lGLWidget->makeCurrent();   // The current context must be set before resizing the mVgGraphicsView.
    QHBoxLayout* lWidgetLayout = new QHBoxLayout(this);
    lWidgetLayout->setContentsMargins(0, 0, 0, 0);
    lWidgetLayout->setSpacing(0);
    lWidgetLayout->addWidget(mVgGraphicsView);

    setAttribute(Qt::WA_AcceptTouchEvents);
}

VgQtWidget::~VgQtWidget ()
{
    delete mVgGraphicsView;
    delete mVgScene;
}

// Handle resize events
void VgQtWidget::handleVgSizeChanged (QResizeEvent* event)
{
    int lWidth = event->size().width();
    int lHeight = event->size().height();

    if (this->parent() != NULL && ((QtVisioSample*)this->parent())->editLayerAndCameraHandler() != NULL)
    {
        ((QtVisioSample*)this->parent())->editLayerAndCameraHandler()->refreshParameters(lWidth, lHeight);
        ((QtVisioSample*)this->parent())->configureStackedLayerAndCameraHandler();
    }
}

VgQtScene* VgQtWidget::editScene()
{
    return mVgScene;
}

void VgQtWidget::setInteractionMode(VgQtScene::InteractionMode pMode)
{
    mVgScene->setInteractionMode(pMode);
}

VgQtGraphicsView* VgQtWidget::editView()
{
    return mVgGraphicsView;
}

./Common/Src/VgMyAvatarDisplay.cpp

/*
* Copyright 2012, Visioglobe SAS
* ALL RIGHTS RESERVED
*
*
* LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
* distribute, and create derivative works from this Source Code,
* provided that: (1) the user reproduces this entire notice within
* both source and binary format redistributions and any accompanying
* materials such as documentation in printed or electronic format;
* (2) the Source Code is not to be used, or ported or modified for
* use, except in conjunction with Visioglobe SDK; and (3) the
* names of Visioglobe SAS may not be used in any
* advertising or publicity relating to the Source Code without the
* prior written permission of Visioglobe.  No further license or permission
* may be inferred or deemed or construed to exist with regard to the
* Source Code or the code base of which it forms a part. All rights
* not expressly granted are reserved.
*
* This Source Code is provided to Licensee AS IS, without any
* warranty of any kind, either express, implied, or statutory,
* including, but not limited to, any warranty that the Source Code
* will conform to specifications, any implied warranties of
* merchantability, fitness for a particular purpose, and freedom
* from infringement, and any warranty that the documentation will
* conform to the program, or any warranty that the Source Code will
* be error free.
*
* IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
* LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
* ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
* SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
* OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
* PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
* OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
* USE, THE SOURCE CODE.
*
* Contact information:  Visioglobe SAS,
* 300, avenue des papeteries,
* 38190 Villard-Bonnot
* FRANCE
* or:  http://www.visioglobe.com
*/

#include "VgMyAvatarDisplay.h"

#include "VgApplication/VgIApplication.h"
#include "VgApplication/VgIModuleManager.h"

#include "VgEngine/VgIEngine.h"
#include "VgEngine/VgInstanceFactory.h"
#include "VgEngine/VgLayer.h"
#include "VgEngine/VgLayerManager.h"
#include "VgEngine/VgPosition.h"
#include "VgEngine/VgPositionToolbox.h"
#include "VgEngine/VgAnimation.h"
#include "VgEngine/VgSinusoidalVectorOffsetFunctorDescriptor.h"
#include "VgEngine/VgVectorInterpolationFunctorDescriptor.h"

#include "Modules/3D/VgI3DModule.h"
#include "Modules/3D/VgPoint.h"

#include "Modules/Map/VgIMapModule.h"

#include "Modules/Navigation/VgINavigation.h"

#include "VgMyTextureLoader.h"

#include <assert.h>
// For M_PI definition
#define _USE_MATH_DEFINES
#include <math.h>

VgMyAvatarDisplay::VgMyAvatarDisplay(VgApplication::VgIApplication* pVgApplication, VgMyTextureLoader* pTextureLoader, bool pDoesFollowRoute)
: mVgApplication(pVgApplication)
, mTextureLoader(pTextureLoader)
, mAvatarPoint(NULL)
, mIsAvatarVisible(false)
, mDoesFollowRoute(pDoesFollowRoute)
{
    assert(mTextureLoader != NULL);

    if (!mTextureLoader->isImageSet("avatar"))
    {
        mTextureLoader->setImage("avatar", "avatar.png");
    }

    if (!mTextureLoader->isMarkerSet("avatar"))
    {
        mTextureLoader->setMarker("avatar","avatar");
    }
}

VgMyAvatarDisplay::~VgMyAvatarDisplay()
{
    clear();
}

void VgMyAvatarDisplay::updateWithPosition(VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigation > const& pNavigation, const VgEngine::VgPosition& pPosition)
{
    if (mDoesFollowRoute)
    {
        if (pNavigation.isValid())
        {
            mPosition = pNavigation->getClosestPositionOnRoute();
        }
        else
        {
            // we don't have the navigation.
            return;
        }
    }
    else
    {
        mPosition = pPosition;
    }
    VgEngine::VgPosition lPointAvatarPosition(mPosition);
    lPointAvatarPosition.mZOrAltitude = 6.0;    // Offset by 6 on the Z-axis to be on top of the layers geometry

    if (!mAvatarPoint)
    {
        float lDuration = 1.0f;

        // Creates the Pin that will display the avatar
        // Setup avatar representing the physical position
        VgEngine::VgRefPtr< Vg3DModule::VgPointDescriptor > lDescriptor = Vg3DModule::VgPointDescriptor::create();
        lDescriptor->mPosition = lPointAvatarPosition;
        lDescriptor->mAltitudeMode = VgEngine::eAbsolute;
        lDescriptor->mVisibilityRampStartVisible = 0.0f;
        lDescriptor->mVisibilityRampFullyVisible = 0.0f;

        lDescriptor->mGeometryConstantSizeDistance = 100.0f;
        lDescriptor->mMarkerDescriptors.push_back(mTextureLoader->getMarker("avatar"));

        lDescriptor->mDrawOnTop = true;
        
        // Create the POI
        mAvatarPoint = mVgApplication->editEngine()->editInstanceFactory()->instantiate(VgEngine::VgConstRefPtr< Vg3DModule::VgPoint::Descriptor >(lDescriptor));
        
        // Add a simple scale pulse animation
        VgEngine::VgRefPtr< VgEngine::VgAnimationDescriptor > lAnimDescr = VgEngine::VgAnimationDescriptor::create();
        VgEngine::VgRefPtr< VgEngine::VgSinusoidalVectorOffsetFunctorDescriptor > lFuncDescr = VgEngine::VgSinusoidalVectorOffsetFunctorDescriptor::create();
        
        lFuncDescr->mBaseVector[0] = 1.0f;
        lFuncDescr->mBaseVector[1] = 1.0f;
        lFuncDescr->mBaseVector[2] = 1.0f;

        lFuncDescr->mVector[0] = 0.1f;
        lFuncDescr->mVector[1] = 0.1f;
        lFuncDescr->mVector[2] = 0.1f;

        lFuncDescr->mStartPhase = -M_PI;
        lFuncDescr->mEndPhase = M_PI;
        lFuncDescr->mStartTime = 0.0f;
        lFuncDescr->mEndTime = lDuration;

        lAnimDescr->mDuration = lDuration;
        lAnimDescr->mLoopMode = VgEngine::VgLoopModes::mscLoop;
        lAnimDescr->mCallback = NULL;
        lAnimDescr->mFunctorDescriptors[VgEngine::VgAnimationChannels::mscLocalScaleChannel] = lFuncDescr;
        VgEngine::VgRefPtr< VgEngine::VgAnimation > lAnim = mVgApplication->editEngine()->editInstanceFactory()->instantiate(lAnimDescr);
        mAvatarPoint->setAnimation("pulseAnim", lAnim);
        lAnim->start();
    }
    else 
    {
        VgEngine::VgPosition lStartPosition = mAvatarPoint->getPosition();
        VgEngine::VgPosition lEndPosition = lPointAvatarPosition;
        double lDistance = mVgApplication->editEngine()->getPositionToolbox()->computeDistance(lStartPosition, lEndPosition);
        if (lDistance < 1.0e-1)
        {
            // Non-animated version
            mAvatarPoint->setPosition(lPointAvatarPosition);
        }
        else
        {
            // Animated version
            if (!mAvatarPoint->getAnimation("positionAnim") || !mAvatarPoint->getAnimation("positionAnim")->isPlaying())
            {
                VgEngine::VgRefPtr< VgEngine::VgAnimationDescriptor > lAnimDescr = VgEngine::VgAnimationDescriptor::create();
                VgEngine::VgRefPtr< VgEngine::VgVectorInterpolationFunctorDescriptor> lFuncDescr = VgEngine::VgVectorInterpolationFunctorDescriptor::create();
                lFuncDescr->mStartTime = 0.0;
                lFuncDescr->mStartPosition = lStartPosition;
                lFuncDescr->mEndPosition = lEndPosition;

                float lAnimationDuration = log(lDistance+1) * 0.05;
                lFuncDescr->mEndTime = lAnimationDuration;
                lAnimDescr->mDuration = lAnimationDuration;

                lFuncDescr->mCubic = false;
                
                lAnimDescr->mFunctorDescriptors[VgEngine::VgAnimationChannels::mscPositionChannel] = lFuncDescr;
                VgEngine::VgRefPtr< VgEngine::VgAnimation > lAnim = mVgApplication->editEngine()->editInstanceFactory()->instantiate(lAnimDescr);
                mAvatarPoint->setAnimation("positionAnim", lAnim);
                lAnim->start();
            }
        }
    }
}

void VgMyAvatarDisplay::clear()
{
    hide();
    mAvatarPoint = NULL;
}

void VgMyAvatarDisplay::show()
{
    if (mAvatarPoint.isValid())
    {
        VgMapModule::VgIMapModule* lMapModule = static_cast< VgMapModule::VgIMapModule* >(mVgApplication->editModuleManager()->queryModule("Map"));
        std::string lLayerName;
        // We don't use the mAvatar->getPosition() as it has been offset by 6 on the Z-axis to be on top of the layers geometry
        if (lMapModule != NULL && lMapModule->getLayerForPosition(mPosition, lLayerName))
        {
            if (!mIsAvatarVisible || lLayerName != mLastAvatarLayerName)
            {
                VgEngine::VgRefPtr< VgEngine::VgLayer > lLayer = mVgApplication->editEngine()->editLayerManager()->editLayer(lLayerName);
                if (lLayer)
                {
                    mIsAvatarVisible = true;
                    mAvatarPoint->setLayer(lLayer);
                    mLastAvatarLayerName = lLayerName;
                }
            }
        }
    }
}

void VgMyAvatarDisplay::hide()
{
    if (mAvatarPoint.isValid())
    {
        mIsAvatarVisible = false;
        mAvatarPoint->setLayer(NULL);
    }
}

bool VgMyAvatarDisplay::isVisible()
{
    return mIsAvatarVisible;
}

./Common/Src/VgMyBasicApplicationController.cpp

/*
* Copyright 2012, Visioglobe SAS
* ALL RIGHTS RESERVED
*
*
* LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
* distribute, and create derivative works from this Source Code,
* provided that: (1) the user reproduces this entire notice within
* both source and binary format redistributions and any accompanying
* materials such as documentation in printed or electronic format;
* (2) the Source Code is not to be used, or ported or modified for
* use, except in conjunction with Visioglobe SDK; and (3) the
* names of Visioglobe SAS may not be used in any
* advertising or publicity relating to the Source Code without the
* prior written permission of Visioglobe.  No further license or permission
* may be inferred or deemed or construed to exist with regard to the
* Source Code or the code base of which it forms a part. All rights
* not expressly granted are reserved.
*
* This Source Code is provided to Licensee AS IS, without any
* warranty of any kind, either express, implied, or statutory,
* including, but not limited to, any warranty that the Source Code
* will conform to specifications, any implied warranties of
* merchantability, fitness for a particular purpose, and freedom
* from infringement, and any warranty that the documentation will
* conform to the program, or any warranty that the Source Code will
* be error free.
*
* IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
* LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
* ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
* SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
* OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
* PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
* OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
* USE, THE SOURCE CODE.
*
* Contact information:  Visioglobe SAS,
* 300, avenue des papeteries,
* 38190 Villard-Bonnot
* FRANCE
* or:  http://www.visioglobe.com
*/

#include "VgMyBasicApplicationController.h"

#include <assert.h>
#define _USE_MATH_DEFINES
#include <math.h>

#include "VgApplication/VgIApplication.h"
#include "VgApplication/VgIModuleManager.h"
#include "VgApplication/VgIModule.h"

#include "VgEngine/VgAnimation.h"
#include "VgEngine/VgIEngine.h"
#include "VgEngine/VgIDatabase.h"
#include "VgEngine/VgInstanceFactory.h"
#include "VgEngine/VgLayer.h"
#include "VgEngine/VgLayerManager.h"
#include "VgEngine/VgPositionToolbox.h"

#include "Modules/Map/VgIMapModule.h"

#include "Modules/Routing/VgIRoute.h"
#include "Modules/Routing/VgIRouteCallback.h"
#include "Modules/Routing/VgIRouteRequest.h"

#include "Modules/Navigation/VgINavigation.h"
#include "Modules/Navigation/VgINavigationInstruction.h"
#include "Modules/Navigation/VgINavigationModule.h"
#include "Modules/Navigation/VgINavigationRequest.h"

#include "VgMyRouteDisplay.h"
#include "VgMyRoutingHelper.h"
#include "VgMyInstructionDisplay.h"
#include "VgMyNavigationCreator.h"
#include "VgMyNavigationPositionDisplay.h"
#include "VgMyLayerAndCameraHandler.h"
#include "VgMyNavigationPositionDisplay.h" 
#include "VgMyTextureLoader.h"

VgMyBasicRouteCallback::VgMyBasicRouteCallback(VgMyBasicApplicationController* pController)
: mController(pController)
{}

VgMyBasicRouteCallback::~VgMyBasicRouteCallback()
{}

void VgMyBasicRouteCallback::notifyRouteComputed( VgRoutingModule::VgRouteRequestStatus pStatus, VgEngine::VgRefPtr< VgRoutingModule::VgIRoute > pRoute)
{
    mController->notifyRouteComputed(pStatus, pRoute);
}

VgMyBasicNavigationCallback::VgMyBasicNavigationCallback(VgMyBasicApplicationController* pController)
: mController(pController)
{}

VgMyBasicNavigationCallback::~VgMyBasicNavigationCallback()
{}

bool VgMyBasicNavigationCallback::notifyNavigationComputed(VgNavigationModule::VgNavigationRequestStatus pStatus, VgEngine::VgRefPtr< VgNavigationModule::VgINavigation > pNavigation)
{
    return mController->notifyNavigationComputed(pStatus, pNavigation);
}

VgMyBasicNavigationListener::VgMyBasicNavigationListener(VgMyBasicApplicationController* pController)
: mController(pController)
{}

VgMyBasicNavigationListener::~VgMyBasicNavigationListener()
{}

void VgMyBasicNavigationListener::notifyPositionUpdated (VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigation > const& pNavigation, const VgEngine::VgPosition& pPosition, double pTime)
{
    mController->notifyPositionUpdated(pNavigation, pPosition, pTime);
}

void VgMyBasicNavigationListener::notifyNewInstruction (VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigation > const& pNavigation, unsigned int pIndex)
{
    mController->notifyNewInstruction(pNavigation, pIndex);
}

VgMyBasicApplicationController::VgMyBasicApplicationController(VgApplication::VgIApplication& pApplication,VgMyTextureLoader* pTextureLoader)
: mVgApplication(pApplication)
, mLayerAndCameraHandler(NULL)
, mRouteCreator(NULL)
, mNavigationCreator(NULL)
, mRoute(NULL)
, mNavigation(NULL)
, mMaximumInstructionNumber(99999) // no limit
, mTextureLoader(pTextureLoader)
, mRouteCallback(new VgMyBasicRouteCallback(this))
, mNavigationCallback(new VgMyBasicNavigationCallback(this))
, mNavigationListener(new VgMyBasicNavigationListener(this))
{}

VgMyBasicApplicationController::~VgMyBasicApplicationController() 
{
    unloadConfiguration();
    deleteRoute();
}

bool VgMyBasicApplicationController::loadConfiguration(const std::string& pConfiguration, const unsigned int pSecretKey, const std::string& pLicenseURL, const int pDataset)
{
    bool lSuccess = mVgApplication.editEngine()->editDatabase()->loadConfiguration(pConfiguration, pSecretKey, pLicenseURL);

    if (lSuccess)
    {
        lSuccess = mVgApplication.editEngine()->editDatabase()->selectDataset(pDataset);
        if (lSuccess)
        {
            // make sure we have some layers
            lSuccess =  (mVgApplication.editEngine()->editLayerManager()->editLayers().size() > 0) ?  true : false;

            if (!lSuccess)
            {
                unloadConfiguration();
            }
        }
    }
    return lSuccess;
}

void VgMyBasicApplicationController::unloadConfiguration()
{
    mVgApplication.editEngine()->editDatabase()->unloadConfiguration();
}

bool VgMyBasicApplicationController::setRoutePoint(VgMyRouteCreator::RoutePoint pPoint, const std::string& pPlaceID)
{
    bool lSuccess = false;
    if (mRouteCreator != NULL)
    {
        lSuccess = mRouteCreator->setRoutePoint(pPoint, pPlaceID);
        if (lSuccess )
        {
            if (mRouteCreator->isRoutePointSet(VgMyRouteCreator::eStart) &&
                mRouteCreator->isRoutePointSet(VgMyRouteCreator::eEnd))
            {
                // Compute the route. It will work only if two points have already been set.
                mRouteCreator->computeRoute();
            }
        }
    }
    return lSuccess;
}

bool VgMyBasicApplicationController::setRoutePoint(VgMyRouteCreator::RoutePoint pPoint, const VgEngine::VgPosition& pPosition)
{
    bool lSuccess = false;
    if (mRouteCreator != NULL)
    {
        lSuccess = mRouteCreator->setRoutePoint(pPoint, pPosition);
        if (lSuccess )
        {
            if (mRouteCreator->isRoutePointSet(VgMyRouteCreator::eStart) &&
                mRouteCreator->isRoutePointSet(VgMyRouteCreator::eEnd))
            {
                // Compute the route. It will work only if two points have already been set.
                mRouteCreator->computeRoute();
            }
        }
    }
    return lSuccess;
}


void VgMyBasicApplicationController::resetRoutePoint(VgMyRouteCreator::RoutePoint pPoint)
{
    if (mRouteCreator)
    {
        mRouteCreator->resetRoutePoint(pPoint);
    }
}

bool VgMyBasicApplicationController::isRoutePointSet(VgMyRouteCreator::RoutePoint pPoint)
{
    bool lResult = false;
    if (mRouteCreator)
    {
        lResult = mRouteCreator->isRoutePointSet(pPoint);
    }
    return lResult;
}

VgRoutingModule::VgIRouteRequestParameters* VgMyBasicApplicationController::editRoutingRequestParameters()
{
    if (mRouteCreator)
    {
        return mRouteCreator->editRoutingRequestParameters();
    }
    return NULL;
}
void VgMyBasicApplicationController::resetRoutingRequestParameters()
{
    if (mRouteCreator)
    {
        mRouteCreator->resetRoutingRequestParameters();
    }
}

// works only if both end points are set
void VgMyBasicApplicationController::computeRoute()
{
    if (mRouteCreator)
    {
        mRouteCreator->computeRoute();
    }
}

void VgMyBasicApplicationController::setAvoidStairs(bool pDisabledFriendly)
{
    if (mRouteCreator)
    {
        mRouteCreator->setAvoidStairs(pDisabledFriendly);
    }
}

VgEngine::VgRefPtr< VgEngine::VgAnimationDescriptor > VgMyBasicApplicationController::getRoutePointHighlightAnimationDescriptor ()
{
    if (mRouteCreator)
    {
        return mRouteCreator->getRoutePointHighlightAnimationDescriptor();
    }
    return NULL;
}

void VgMyBasicApplicationController::deleteRoute()
{
    // Clear all route displays
    for (std::list<VgMyRouteDisplay*>::iterator lItRouteDisplay = mRouteDisplays.begin(), lItEnd = mRouteDisplays.end();
        lItRouteDisplay != lItEnd;
        lItRouteDisplay++)
    {
        VgMyRouteDisplay* lRouteDisplay = *lItRouteDisplay;
        if (lRouteDisplay != NULL)
        {
            lRouteDisplay->clear();
        }
    }

    // Clear all navigation
    for (std::list<VgMyInstructionDisplay*>::iterator lItInstructionDisplay = mInstructionsDisplays.begin(), lItEnd = mInstructionsDisplays.end();
        lItInstructionDisplay != lItEnd;
        lItInstructionDisplay++)
    {
        VgMyInstructionDisplay* lInstructionDisplay = *lItInstructionDisplay;
        if (lInstructionDisplay != NULL)
        {
            lInstructionDisplay->clear();
        }
    }

    clearNavigationPositionDisplays();

    mRoute = NULL;
    mNavigation = NULL;
}

void VgMyBasicApplicationController::setLayerAndCameraHandler(VgMyLayerAndCameraHandler* pHandler)
{
    mLayerAndCameraHandler = pHandler;
}

void VgMyBasicApplicationController::setRouteCreator(VgMyRouteCreator* pCreator)
{
    mRouteCreator = pCreator;
}
VgMyRouteCreator* VgMyBasicApplicationController::getRouteCreator() const
{
    return mRouteCreator;
}

void VgMyBasicApplicationController::setRouteStyle (VgMyRouteStyler::RouteStyle pRouteStyle, bool pRecomputeRoute)
{
    if (mRouteCreator != NULL)
    {
        mRouteCreator->setRouteStyle(pRouteStyle,pRecomputeRoute);
    }
}
VgMyRouteStyler::RouteStyle VgMyBasicApplicationController::getRouteStyle () const
{
    if (mRouteCreator != NULL)
    {
        return mRouteCreator->getRouteStyle();
    }
    // if we can't say it is classic.
    return VgMyRouteStyler::eClassic;
}


void VgMyBasicApplicationController::addRouteDisplay(VgMyRouteDisplay* pDisplay)
{
    mRouteDisplays.push_back(pDisplay);
}

void VgMyBasicApplicationController::notifyRouteComputed(VgRoutingModule::VgRouteRequestStatus pStatus, VgEngine::VgRefPtr< VgRoutingModule::VgIRoute > const& pRoute)
{
    deleteRoute();
    

    mRoute = pRoute;

    for (std::list<VgMyRouteDisplay*>::iterator lItRouteDisplay = mRouteDisplays.begin(), lItEnd = mRouteDisplays.end();
        lItRouteDisplay != lItEnd;
        lItRouteDisplay++)
    {
        VgMyRouteDisplay* lRouteDisplay = *lItRouteDisplay;
        if (lRouteDisplay != NULL)
        {
            if (pStatus == VgRoutingModule::eSuccess)
            {
                assert(pRoute != NULL);
                
                bool lSuccess = lRouteDisplay->createRouteObjects(pRoute);
                if (lSuccess)
                {
                    lRouteDisplay->show();

                    // NOTE : The navigation can be computed even if there is no RouteDisplay, but the user-experience would be less effective.
                    if (mNavigationCreator != NULL)
                    {
                        VgNavigationModule::VgINavigationRequestParameters lNavigationParams(0, mNavigationCallback, pRoute);
                        // Customize other attributes here.
                        lNavigationParams.mModalityParameters["shuttle"][VgNavigationModule::eStraightAngleThreshold] = 180.0f;
                        lNavigationParams.mModalityParameters["shuttle"][VgNavigationModule::eDistanceFromCouloirThreshold] = 1000.0f;
                        lNavigationParams.mMergeFloorChangeInstructions = false;
                        mNavigationCreator->createNavigation(lNavigationParams);
                    }
                }
            }
        }
    }
}

bool VgMyBasicApplicationController::notifyNavigationComputed (VgNavigationModule::VgNavigationRequestStatus pStatus, VgEngine::VgRefPtr< VgNavigationModule::VgINavigation > const& pNavigation)
{
    if(pStatus == VgNavigationModule::eSuccess)
    {
        mNavigation = pNavigation;
        pNavigation->addListener(mNavigationListener);
    }

    return true;
}

void VgMyBasicApplicationController::notifyPositionUpdated(VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigation > const& pNavigation, const VgEngine::VgPosition& pPosition, double pTime)
{
    // Notifies all listeners
    for (std::list<VgMyNavigationPositionDisplay*>::iterator lItPosDisplay = mPositionDisplays.begin(), lItEnd = mPositionDisplays.end();
        lItPosDisplay != lItEnd;
        lItPosDisplay++)
    {
        VgMyNavigationPositionDisplay* lPosDisplay = *lItPosDisplay;
        if (lPosDisplay != NULL)
        {
            lPosDisplay->updateWithPosition(pNavigation, pPosition);
            lPosDisplay->show();
        }
    }
}

void VgMyBasicApplicationController::notifyNewInstruction(VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigation > const& pNavigation, unsigned int pIndex)
{
    // Notifies all listeners
    for (std::list<VgMyInstructionDisplay*>::iterator lItInstructionDisplay = mInstructionsDisplays.begin(), lItEnd = mInstructionsDisplays.end();
        lItInstructionDisplay != lItEnd;
        lItInstructionDisplay++)
    {
        VgMyInstructionDisplay* lInstructionDisplay = *lItInstructionDisplay;
        if (lInstructionDisplay != NULL)
        {
            lInstructionDisplay->updateWithInstruction(pNavigation, pIndex);
            lInstructionDisplay->show();
        }
    }
}


void VgMyBasicApplicationController::gotoLayer(const unsigned int pLayerIndex, bool pIsAnimated)
{
    mLayerAndCameraHandler->gotoLayer(pLayerIndex, pIsAnimated);
}


unsigned int VgMyBasicApplicationController::getNumberOfLayers()
{
    return mLayerAndCameraHandler->getNumberOfLayers();
}


bool VgMyBasicApplicationController::getLayerName(const unsigned int pLayerIndex, std::string& pLayerNameOut)
{
    return mLayerAndCameraHandler->getLayerName(pLayerIndex,pLayerNameOut);
}

void VgMyBasicApplicationController::goToInstruction(const unsigned int pInstructionIndex)
{
    if (mNavigation && pInstructionIndex < (mNavigation->getNumInstructions()))
    {
        notifyNewInstruction(mNavigation, pInstructionIndex);
        animateToInstruction(mNavigation, pInstructionIndex);
    }
}


bool VgMyBasicApplicationController::has3DModule() const
{
    return (mVgApplication.editModuleManager()->queryModule("3D") != NULL);
}


bool VgMyBasicApplicationController::hasMapModule() const
{
    return (mVgApplication.editModuleManager()->queryModule("Map") != NULL);
}


bool VgMyBasicApplicationController::hasRoutingModule() const
{
    return (mVgApplication.editModuleManager()->queryModule("Routing") != NULL);
}

bool VgMyBasicApplicationController::hasNavigationModule() const
{
    return (mVgApplication.editModuleManager()->queryModule("Navigation") != NULL);
}


bool VgMyBasicApplicationController::isGlobalView()
{
    return mLayerAndCameraHandler->isGlobalView(); 
}


void VgMyBasicApplicationController::switchToGlobalView(bool pIsAnimated)
{
    return mLayerAndCameraHandler->switchToGlobalView(pIsAnimated);
}


void VgMyBasicApplicationController::switchToDetailedView(bool pIsAnimated)
{
    return mLayerAndCameraHandler->switchToDetailedView(pIsAnimated);
}


const std::string& VgMyBasicApplicationController::getFocusedLayerName()
{
    return mLayerAndCameraHandler->getFocusedLayerName(); 
}


void VgMyBasicApplicationController::gotoLayer(const std::string& pLayerName, bool pIsAnimated)
{
    return mLayerAndCameraHandler->gotoLayer(pLayerName, pIsAnimated);
}


void VgMyBasicApplicationController::gotoViewpoint(const VgEngine::VgIViewPoint& pViewPoint, const std::string& pLayerName, bool pIsAnimated)
{
    return mLayerAndCameraHandler->gotoViewpoint(pViewPoint, pLayerName, pIsAnimated);
}

void VgMyBasicApplicationController::gotoLookAtPosition(const VgEngine::VgPosition& pPosition, const std::string& pLayerName, bool pIsAnimated)
{
    return mLayerAndCameraHandler->gotoLookAtPosition(pPosition, pLayerName, pIsAnimated);
}



void VgMyBasicApplicationController::layerWillChangeFrom(VgMyLayerAndCameraHandler* pSender, const std::string& pFloorFrom, const std::string& pFloorTo)
{
    for (std::list<VgMyLayerAndCameraListener*>::iterator lItListener = mLayerAndCameraListeners.begin(), lItEnd = mLayerAndCameraListeners.end();
        lItListener != lItEnd;
        lItListener++)
    {
        (*lItListener)->layerWillChangeFrom(pSender, pFloorFrom, pFloorTo);
    }
}


void VgMyBasicApplicationController::layerChangedTo(VgMyLayerAndCameraHandler* pSender, const std::string& pFloorFrom, const std::string& pFloorTo)
{
    for (std::list<VgMyLayerAndCameraListener*>::iterator lItListener = mLayerAndCameraListeners.begin(), lItEnd = mLayerAndCameraListeners.end();
        lItListener != lItEnd;
        lItListener++)
    {
        (*lItListener)->layerChangedTo(pSender, pFloorFrom, pFloorTo);
    }
}

void VgMyBasicApplicationController::viewWillChange(VgMyLayerAndCameraHandler* pSender, const bool pDoesChangeFromGlobalToDetailed)
{
    for (std::list<VgMyLayerAndCameraListener*>::iterator lItListener = mLayerAndCameraListeners.begin(), lItEnd = mLayerAndCameraListeners.end();
         lItListener != lItEnd;
         lItListener++)
    {
        (*lItListener)->viewWillChange(pSender, pDoesChangeFromGlobalToDetailed);
    }
}

void VgMyBasicApplicationController::viewDidChange(VgMyLayerAndCameraHandler* pSender, const bool pDoesChangeFromGlobalToDetailed)
{
    for (std::list<VgMyLayerAndCameraListener*>::iterator lItListener = mLayerAndCameraListeners.begin(), lItEnd = mLayerAndCameraListeners.end();
         lItListener != lItEnd;
         lItListener++)
    {
        (*lItListener)->viewDidChange(pSender, pDoesChangeFromGlobalToDetailed);
    }
}


void VgMyBasicApplicationController::addLayerAndCameraListener(VgMyLayerAndCameraListener* pListener)
{
    mLayerAndCameraListeners.push_back(pListener);
}


void VgMyBasicApplicationController::setNavigationCreator(VgMyNavigationCreator* pCreator)
{
    mNavigationCreator = pCreator;
}


void VgMyBasicApplicationController::addInstructionDisplay(VgMyInstructionDisplay* pDisplay)
{
    mInstructionsDisplays.push_back(pDisplay);
}


void VgMyBasicApplicationController::addNavigationPositionDisplay(VgMyNavigationPositionDisplay* pDisplay)
{
    mPositionDisplays.push_back(pDisplay);
}


void VgMyBasicApplicationController::clearNavigationPositionDisplays()
{
    for (std::list<VgMyNavigationPositionDisplay*>::iterator lItPosDisplay = mPositionDisplays.begin(), lItEnd = mPositionDisplays.end();
        lItPosDisplay != lItEnd;
        lItPosDisplay++)
    {
        VgMyNavigationPositionDisplay* lPosDisplay = *lItPosDisplay;
        if (lPosDisplay != NULL)
        {
            lPosDisplay->clear();
        }
    }
}


void VgMyBasicApplicationController::refreshParameters(unsigned int pWidth, unsigned int pHeight)
{
    mLayerAndCameraHandler->refreshParameters(pWidth, pHeight);
}


void VgMyBasicApplicationController::animateToInstruction(VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigation > const& pNavigation, unsigned int pIndex)
{
    VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigationInstruction > lInstruction = pNavigation->getInstruction(pIndex);
    if (lInstruction)
    {
        VgEngine::VgPosition lInstructionPosition = lInstruction->getPosition();
        mLayerAndCameraHandler->gotoLookAtPosition(lInstructionPosition, lInstruction->getLayer());
    }
}

void VgMyBasicApplicationController::updatePosition(const VgEngine::VgPosition& pPosition)
{
    /*
     * IMPORTANT NOTE: this call should be made from the main thread.
     * mNavigation->updateCurrentPosition() will broadcast a 
     */
    if (mNavigation && !mLayerAndCameraHandler->isGlobalView())
    {
        mNavigation->updateCurrentPosition(pPosition, 0);
    }
    else
    {
        // The SDK does not take time into consideration for the moment.
        notifyPositionUpdated(NULL,pPosition,0.0);
    }
}

./Common/Src/VgMyFloorPoiCallback.cpp

/*
 * Copyright 2011, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */
 
#include "VgMyFloorPoiCallback.h"

#include "VgApplication/VgIApplication.h"

#include "VgEngine/VgICamera.h"
#include "VgEngine/VgIEngine.h"

#include "Modules/3D/VgIGeometryEvent.h"

#include "VgMyLayerAndCameraHandler.h"

VgMyFloorPoiCallback::VgMyFloorPoiCallback(VgMyLayerAndCameraHandler* pHandler, VgEngine::VgICamera* pCamera, const VgEngine::VgPosition& pPosition, const std::string& pLayerName)
    : mHandler(pHandler)
    , mCamera(pCamera)
    , mGoToPos(pPosition)
    , mLayerName(pLayerName)
{}

VgMyFloorPoiCallback::~VgMyFloorPoiCallback()
{
    mHandler = NULL;
}

void VgMyFloorPoiCallback::handleGeometryEvent (const Vg3DModule::VgIGeometryEvent& pEvent)
{
    if(NULL != mHandler)
    {
        mHandler->gotoLookAtPosition(mGoToPos, mLayerName);
    }
}

./Common/Src/VgMyInstructionPathDisplay.cpp

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

#include "VgMyInstructionPathDisplay.h"

#include "VgApplication/VgIApplication.h"

#include "VgEngine/VgIEngine.h"
#include "VgEngine/VgLayerManager.h"
#include "VgEngine/VgLayer.h"
#include "VgEngine/VgInstanceFactory.h"
#include "VgEngine/VgTypes.h"

#include "Modules/3D/VgLine.h"

#include "Modules/Navigation/VgINavigation.h"
#include "Modules/Navigation/VgINavigationInstruction.h"


VgMyInstructionPathDisplay::VgMyInstructionPathDisplay (VgApplication::VgIApplication* pVgApplication)
: mVgApplication(pVgApplication)
, mInstruction(NULL)
, mLine(NULL)
, mIsLineVisible(false)
{}

VgMyInstructionPathDisplay::~VgMyInstructionPathDisplay ()
{
    clear();
}

void VgMyInstructionPathDisplay::updateWithInstruction(VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigation > const& pNavigation, unsigned int pIndex)
{
    mInstruction = pNavigation->getInstruction(pIndex);
      
        
        if (mInstruction->getManeuverType() != VgNavigationModule::eVgManeuverTypeGoUp &&
            mInstruction->getManeuverType() != VgNavigationModule::eVgManeuverTypeGoDown)
        {
            VgEngine::VgRefPtr< Vg3DModule::VgLineDescriptor > lCurrentLD = Vg3DModule::VgLineDescriptor::create();
            
            const std::vector<VgEngine::VgPosition>& lPositions = mInstruction->getInstructionPositions();
            std::vector<VgEngine::VgPosition>::const_iterator lPosIter;
            
            const VgEngine::VgColor lEvenColor = VgEngine::VgColor(1.0, 0.0, 0.0, 1.0);
            const VgEngine::VgColor lOddColor = VgEngine::VgColor(1.0, 1.0, 0.0, 1.0);
            bool lParity = false;
            lCurrentLD->mColors.clear();
            for (lPosIter = lPositions.begin(); lPosIter != lPositions.end(); ++lPosIter)
            {
                VgEngine::VgPosition lPosition = *lPosIter;
                lPosition.mZOrAltitude = 5.0;
                lCurrentLD->mPositions.push_back(lPosition);
                lCurrentLD->mColors.push_back(lParity ? lEvenColor : lOddColor );
                lParity = !lParity;
            }
            
            lCurrentLD->mLineType = Vg3DModule::eGeometryConstantSize;
            lCurrentLD->mTextureAnimationSpeed = 4;
            lCurrentLD->mWidths.clear();
            lCurrentLD->mWidths.push_back(1.0);
            // Set animated image white with no transparency.
            lCurrentLD->mTexture = NULL;
            lCurrentLD->mTextureSize = 1.0;
            
            mLine = mVgApplication->editEngine()->editInstanceFactory()->instantiate(VgEngine::VgConstRefPtr< Vg3DModule::VgLine::Descriptor >(lCurrentLD));
        }
}


    void VgMyInstructionPathDisplay::show()
    {
        if (mLine)
        {
            mIsLineVisible = true;
            mLine->setLayer(mVgApplication->editEngine()->editLayerManager()->editLayer(mInstruction->getLayer()));
        }
    }

    void VgMyInstructionPathDisplay::hide()
    {
        if (mLine.isValid())
        {
            mIsLineVisible = false;
            mLine->setLayer(NULL);
        }
    }

    bool VgMyInstructionPathDisplay::isVisible()
    {
        return mIsLineVisible;
    }

    void VgMyInstructionPathDisplay::clear()
    {
        mInstruction = NULL;
        mLine = NULL;
        mIsLineVisible = false;
    }

./Common/Src/VgMyNavigationHelper.cpp

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

#include "VgMyNavigationHelper.h"

#include "Modules/Navigation/VgINavigationModule.h"
#include "Modules/Navigation/VgINavigation.h"
#include "Modules/Navigation/VgINavigationInstruction.h"

#include "Modules/Map/VgIMapModule.h"

#include <sstream>

const std::string VgMyNavigationHelper::cLanguageStrings [2] =
{
    "en",
    "fr"
};


// You can use a table like this to handle multiple languages.
// This text is in UTF8, on a Visual Studio it will NOT look right.
// but we use trUtf8 in QT to properly handle unicode text right.
const std::string VgMyNavigationHelper::cActionStringTable[cNumLanguages][VgNavigationModule::eVgManeuverTypeMax] =
{
    {
        "<unknown>", // eVgManeuverTypeUnknown
        "Go straight",
        "Turn gentle right",
        "Turn gentle left",
        "Turn right",
        "Turn left",
        "Turn sharp right",
        "Turn sharp left",
        "Make right U-turn",
        "Make left U-turn",
        "Start",
        "You have arrived",
        "Go up to floor %L",
        "Go down to floor %L",
        "Use transportation mode %M",
    },
    {
        "<inconnu>", // eVgManeuverTypeUnknown
        "Continuez tout droit",
        "Tournez légèrement à droite",
        "Tournez légèrement à gauche",
        "Tournez à droite",
        "Tournez à gauche",
        "Tournez fortement à droite",
        "Tournez fortement à gauche",
        "Effectuez un demi-tour à droite",
        "Effectuez un demi-tour à gauche",
        "Départ",
        "Arrivée",
        "Montez à l'étage %L",
        "Descendez à l'étage %L",
        "Changez de moyen de transport: %M",
    },
};

const std::string VgMyNavigationHelper::cNextActionStringTable[cNumLanguages][VgNavigationModule::eVgManeuverTypeMax] =
{
    {
        "<unknown>", // eVgManeuverTypeUnknown
        "go straight",
        "turn gentle right",
        "turn gentle left",
        "turn right",
        "turn left",
        "turn sharp right",
        "turn sharp left",
        "make right U-turn",
        "make left U-turn",
        "start",
        "you have arrived",
        "go up",
        "go down",
        "change transportation mode: %M",
    },
    {
        "<inconnu>", // eVgManeuverTypeUnknown
        "continuez tout droit",
        "tournez légèrement à droite",
        "tournez légèrement à gauche",
        "tournez à droite",
        "tournez à gauche",
        "tournez fortement à droite",
        "tournez fortement à gauche",
        "effectuez un demi-tour à droite",
        "effectuez un demi-tour à gauche",
        "départ",
        "vous serez arrivés",
        "montez",
        "descendez",
        "changez de mode de transport: %M",
    },
};

const std::string VgMyNavigationHelper::cTimeStringTable [cNumLanguages][3] =
{
    {
        "a few seconds",
        "about a minute",
        "about %d minutes",
    },
    {
        "quelques secondes",
        "environ une minute",
        "environ %d minutes",
    },
};

const std::string VgMyNavigationHelper::cStringTable[cNumLanguages][eStringCount]=
{
    {
        " for ",
        " then ",
        " and ",
        " near ",
        " using ",
    },
    {
        " pendant ",
        " puis ",
        " et ",
        " à proximité de ",
        " en empruntant ",
    },
};

VgMyNavigationHelper::VgMyNavigationHelper(VgNavigationModule::VgINavigationModule* pNavModule)
: mNavigationModule(pNavModule)
{}

VgMyNavigationHelper::~VgMyNavigationHelper()
{}

void VgMyNavigationHelper::createNavigation(VgNavigationModule::VgINavigationRequestParameters& pParameters)
{
    VgNavigationModule::VgINavigationRequest* lRequest = mNavigationModule->computeNavigation(&pParameters);
    // Store lRequest to be able to cancel it later if necessary 
    // In this case, no need so we delete it
    if (lRequest != NULL)
    {
        delete lRequest;
    }
}


std::string VgMyNavigationHelper::timeToText (float pTimeInMinutes, int pLang)
{
    if(pLang >= cNumLanguages)
    {
        pLang = 0;
    }
    
    if (pTimeInMinutes < 1.0)
    {
        return cTimeStringTable[pLang][0];
    }
    else if (pTimeInMinutes < 2.0)
    {
        return cTimeStringTable[pLang][1];
    }
    else
    {
        return cTimeStringTable[pLang][2];
    }
}

void replace(std::string& pString, const std::string& pSearched, const std::string& pReplacement)
{
    size_t lFieldStart = pString.find(pSearched);
    while (lFieldStart != pString.npos)
    {
        pString.replace(pString.begin() + lFieldStart, pString.begin() + lFieldStart + pSearched.length(), pReplacement);
        lFieldStart = pString.find(pSearched);
    }
}

void VgMyNavigationHelper::translateInstruction(
    VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigationInstruction > const & pInstruction,
    VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigation > const& pNavigation,
    VgTranslatedInstruction& pTranslated,
    VgMapModule::VgIMapModule& pMapModule,
    int pLang)
{
    //format:
    //  en: {action}[{duration}][{nextAction}[{means}]].
    //  fr: {action}[{duration}][{nextAction}[{means}]].
    //
    //action:
    //  en: "Change transportation mode"    | "Go up"  | "Go down"   | "Go straight"
    //  fr: "Changez de moyen de transport" | "Montez" | "Descendez" | "Continuez"
    //
    //2:
    //  en: " for a few seconds"     | " for about a minute"     | " for about {dur} minutes" | ""
    //  fr: " pendant quelques secondes" | " pendant environ une minute" | " pendant environ {dur} minutes"
    //
    //3: 
    //  en: " then change transportation mode"    | " go up"  | " go down"   | " go straight"
    //  fr: " puis changez de moyen de transport" | " montez" | " descendez" | " continuez"
    //
    //4:
    //  en: " using {placeName}"         | " near {placeName}"
    //  fr: " en empruntant {placeName}" | " à proximité de {placeName}"
    
    // Strings to compose the message
    std::string lStringAction;
    std::string lStringDuration;
    std::string lStringNextAction;
    std::string lStringVincinity;

    // lNextInstr will be null if there is no next instruction (i.e. this one is the last)
    VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigationInstruction > lNextInstr = pNavigation->getInstruction(pInstruction->getIndex() + 1);
    switch (pInstruction->getManeuverType())
    {
        case VgNavigationModule::eVgManeuverTypeChangeModality:
        case VgNavigationModule::eVgManeuverTypeEnd:
        case VgNavigationModule::eVgManeuverTypeGoDown:
        case VgNavigationModule::eVgManeuverTypeGoUp:
        case VgNavigationModule::eVgManeuverTypeStart:
            lStringAction = cActionStringTable[pLang][pInstruction->getManeuverType()];
            break;
            
        case VgNavigationModule::eVgManeuverTypeGoStraight:
            lStringAction = cActionStringTable[pLang][VgNavigationModule::eVgManeuverTypeGoStraight];
            lStringDuration = cStringTable[pLang][eStringFor] + timeToText(pInstruction->getDuration()/60.0f, pLang);
            if (pNavigation->getRequestParameters().mMergeFloorChangeInstructions)
            {
                // When instruction merging is active, we have to test the next
                // instruction's layer/modality to know if we should instruct to change
                // level/transportation.
                if (!lNextInstr)
                {
                    // Last instruction means next action is "you have arrived"
                    lStringNextAction = cStringTable[pLang][eStringThen] + cNextActionStringTable[pLang][VgNavigationModule::eVgManeuverTypeEnd];
                }
                else if (lNextInstr->getLayer() != pInstruction->getLayer())
                {
                    // TODO: Test whether we go up or down
                    lStringNextAction = cStringTable[pLang][eStringThen] + cNextActionStringTable[pLang][VgNavigationModule::eVgManeuverTypeGoUp];
                    if (lNextInstr->getModality() != pInstruction->getModality())
                    {
                        lStringNextAction += cStringTable[pLang][eStringAnd] + cNextActionStringTable[pLang][VgNavigationModule::eVgManeuverTypeChangeModality];
                    }
                }
                else if (lNextInstr->getModality() != pInstruction->getModality())
                {
                    lStringNextAction += cStringTable[pLang][eStringThen] + cNextActionStringTable[pLang][VgNavigationModule::eVgManeuverTypeChangeModality];
                }
            }
            else
            {
                // When instruction merging is inactive, we have to test the next
                // instruction's type to know if we should instruct to change level
                // or transportation mode.
                if (pInstruction->getIndex() < pNavigation->getNumInstructions() - 1)
                {
                    VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigationInstruction > lNextInstr = pNavigation->getInstruction(pInstruction->getIndex() + 1);
                    if (lNextInstr.isValid())
                    {
                        switch (lNextInstr->getManeuverType())
                        {
                            case VgNavigationModule::eVgManeuverTypeChangeModality:
                            case VgNavigationModule::eVgManeuverTypeEnd:
                            case VgNavigationModule::eVgManeuverTypeGoDown:
                            case VgNavigationModule::eVgManeuverTypeGoUp:
                                lStringNextAction = cStringTable[pLang][eStringThen] + cNextActionStringTable[pLang][lNextInstr->getManeuverType()];
                                break;
                            default:
                                break;
                        }
                    }
                }
                else
                {
                    // We are on last instruction, so no next action.
                }
            }
            break;

        default:
            // These are turn left/right instructions
            lStringAction = cActionStringTable[pLang][VgNavigationModule::eVgManeuverTypeGoStraight];
            lStringDuration = cStringTable[pLang][eStringFor] + timeToText(pInstruction->getDuration()/60.0f, pLang);
            lStringNextAction = cStringTable[pLang][eStringThen] + cNextActionStringTable[pLang][pInstruction->getManeuverType()];
            break;
    }

    // Use Natural Guidance information
    bool lSkipNearPlaces = false;
    const std::vector<VgNavigationModule::VgNearPlace>& lPlaces = pInstruction->getNearPlaces();
    if (
        (
            pNavigation->getRequestParameters().mMergeFloorChangeInstructions
            && pInstruction->getIndex() >= pNavigation->getNumInstructions() - 1
        )
        || (
            !pNavigation->getRequestParameters().mMergeFloorChangeInstructions
            && pInstruction->getIndex() >= pNavigation->getNumInstructions() - 2
        )
    )
    {
        lSkipNearPlaces = true;
    }

    // Handle the case where the next instruction is a floor change, we want to use "using" escalator
    // and not near escalator.
    bool lThereIsFloorChange = false;
    if (!pNavigation->getRequestParameters().mMergeFloorChangeInstructions
        && pInstruction->getIndex() < (pNavigation->getNumInstructions() - 2)
        && pNavigation->getInstruction(pInstruction->getIndex()+1)->isEndOrTransitionPoint())
    {
        lThereIsFloorChange = true; 
    }
    
//    typedef std::set<std::string> stringset;
//    const stringset& lAttributes = pInstruction->getAttributes();
//    for (stringset::const_iterator iter = lAttributes.begin(); iter != lAttributes.end(); ++iter)
//    {
//        printf("%s\n",iter->c_str());
//    }
    

    if (!lSkipNearPlaces)
    {
        if (lPlaces.size() > 0)
        {
            std::string lPlaceName;
            pMapModule.getPlaceName(lPlaces[0].mID, lPlaceName);
            if (!lPlaceName.empty())
            {
                if (lThereIsFloorChange)
                {
                    // Maybe this should test only prefix? (skipping first letter)
                    if (lPlaceName.find("scalator") != std::string::npos ||
                        lPlaceName.find("levator") != std::string::npos ||
                        lPlaceName.find("ifts") != std::string::npos)
                    {
                        // we say using, if the near POI is a [E]scalator or [E]levator.
                        // else we say nothing.
                        lStringVincinity = cStringTable[pLang][eStringUsing] + lPlaceName;
                    }
                }
                else 
                {
                    lStringVincinity = cStringTable[pLang][eStringNear] + lPlaceName;
                }
            }
            // else maybe choose another place?
        }
    }

    pTranslated.mMessage = lStringAction + lStringDuration + lStringNextAction + lStringVincinity;
    pTranslated.mBrief = lStringAction;
    pTranslated.mDuration = lStringDuration;
    pTranslated.mDurationInSeconds = pInstruction->getDuration();
    
    replaceTokens(pTranslated.mMessage, pInstruction, lNextInstr);
    replaceTokens(pTranslated.mBrief, pInstruction, lNextInstr);
    replaceTokens(pTranslated.mDuration, pInstruction, lNextInstr);
    
}


void VgMyNavigationHelper::replaceTokens(
    std::string& pStringWithTokens,
    VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigationInstruction > const & pInstructionCurrent,
    VgEngine::VgConstRefPtr< VgNavigationModule::VgINavigationInstruction > const & pInstructionNext)
{
    // Replaces occurrances of a token with contextual data
    if(pInstructionCurrent.isValid())
    {
        int lDurationInMinutes = pInstructionCurrent->getDuration()/60.0f;
        std::stringstream lStream;
        lStream << lDurationInMinutes;
        
        replace(pStringWithTokens, "%d", lStream.str());
        
        replace(pStringWithTokens, "%m", pInstructionCurrent->getModality());
        
        replace(pStringWithTokens, "%l", pInstructionCurrent->getLayer());
    }
    
    if (pInstructionNext.isValid())
    {
        replace(pStringWithTokens, "%M", pInstructionNext->getModality());
        
        replace(pStringWithTokens, "%L", pInstructionNext->getLayer());
    }
}


int VgMyNavigationHelper::getLangId (const std::string& pLangSr)
{
    if (pLangSr.size() < 2)
    {
        return 0;
    }
    std::string lLang2 = pLangSr.substr(0,2);
    for (int i = 0; i < cNumLanguages; ++i)
    {
        if (cLanguageStrings[i] == lLang2)
        {
            return i;
        }
    }
    return 0;
}

./Common/Src/VgMyRoutingHelper.cpp

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */
#include "VgMyRoutingHelper.h"

#include <assert.h>
#include <vector>

#include "VgApplication/VgIApplication.h"
#include "VgApplication/VgIModuleManager.h"

#include "VgEngine/VgBinaryBuffer.h"
#include "VgEngine/VgIEngine.h"
#include "VgEngine/VgInstanceFactory.h"
#include "VgEngine/VgIResourceManager.h"
#include "VgEngine/VgITextureManager.h"
#include "VgEngine/VgLayer.h"
#include "VgEngine/VgLayerManager.h"
#include "VgEngine/VgRefPtr.h"
#include "VgEngine/VgSinusoidalVectorOffsetFunctorDescriptor.h"
#include "VgEngine/VgSplineVectorFunctorDescriptor.h"
#include "VgEngine/VgSplineOrientationQuaternionFunctorDescriptor.h"
#include "VgEngine/VgAxialRotationQuaternionFunctorDescriptor.h"
#include "VgEngine/VgPositionToolbox.h"

#include "Modules/Map/VgPlaceDescriptor.h"

#include "Modules/3D/VgIGeometryCallback.h"
#include "Modules/3D/VgLine.h"
#include "Modules/3D/VgLink.h"
#include "Modules/3D/VgPoint.h"
#include "Modules/3D/VgTextMarkerDescriptor.h"

#include "Modules/Routing/VgIRoute.h"
#include "Modules/Routing/VgIRouteCallback.h"
#include "Modules/Routing/VgIRouteConverter.h"
#include "Modules/Routing/VgIRouteConverterFactory.h"
#include "Modules/Routing/VgIRouteRequest.h"
#include "Modules/Routing/VgIRoutingModule.h"
#include "Modules/Routing/VgIRoutingNode.h"
#include "Modules/Routing/VgIRoutingSolver.h"

#include "VgMyFloorPoiCallback.h"
#include "VgMyTextureLoader.h"

// For M_PI definition
#define _USE_MATH_DEFINES
#include <math.h>

const std::string VgMyRoutingHelper::kStartPointStrID = "VgMyRoutingHelper_StartPoint";
const std::string VgMyRoutingHelper::kEndPointStrID = "VgMyRoutingHelper_EndPoint";

VgMyRoutingHelper::VgMyRoutingHelper(VgApplication::VgIApplication* pVgApplication, VgMyTextureLoader* pTextureLoader, VgEngine::VgRefPtr< VgRoutingModule::VgIRouteCallback >const& pCallback, VgMyLayerAndCameraHandler* pLayerAndCameraHandler)
: mVgApplication(pVgApplication)
, mTextureLoader(pTextureLoader)
, mCallback(pCallback)
, mInstanceFactory(pVgApplication->editEngine()->editInstanceFactory())
, mRoutingModule(NULL)
, mRouteSolver(NULL)
, mRouteConverter2D(NULL)
, mIsRouteVisible(false)
, mRouteStyle(VgMyRouteStyler::eSimplifiedMultiLinePlusAgent)
, mObjectHeightOffset(6.0)
, mLayerAndCameraHandler(pLayerAndCameraHandler)
, mHighlightedRoutePointsAnimationDescr(NULL)
, mRouteStyler(pVgApplication)
{
    
    resetRoutingRequestParameters();
    
    mRoutingModule = (VgRoutingModule::VgIRoutingModule*)mVgApplication->editModuleManager()->queryModule("Routing");
    assert(mRoutingModule != NULL); // This VgMyRoutingHelper should not be created if the routing moule is not available.

    VgRoutingModule::VgIRouteConverterFactory* lRouteConverterFactory = mRoutingModule->getRouteConverterFactory();
    if ( lRouteConverterFactory )
    {
        mRouteConverter2D = lRouteConverterFactory->createConverter(VgRoutingModule::e2D);
    }
    
    mMapModule = static_cast<VgMapModule::VgIMapModule*>(mVgApplication->editModuleManager()->queryModule("Map"));

    assert(mTextureLoader != NULL);

    // Loads Textures
    //mTextureLoader->setImage("track", "2d_track.png");
    mTextureLoader->setImage("track", "2d_track_blue_boomerang.png");
    mTextureLoader->setImage("trackBase", "2d_track_base.png");
    mTextureLoader->setImage("trackBaseFat", "2d_track_base_fat.png");
    mTextureLoader->setImage("stairsUp", "track_stair_up.png");
    mTextureLoader->setImage("stairsDown", "track_stair_down.png");
    mTextureLoader->setImage("start", "track_start.png");
    mTextureLoader->setImage("end", "track_end.png");
    
    // Prepares markers
    mTextureLoader->setMarker("stairsUp", "stairsUp");
    mTextureLoader->setMarker("stairsDown", "stairsDown");
    mTextureLoader->setMarker("start", "start");
    mTextureLoader->setMarker("end", "end");
}

VgMyRoutingHelper::~VgMyRoutingHelper()
{
    clear();
    mHighlightedRoutePointsAnimationDescr = NULL;
    delete mRouteConverter2D;
    mRouteConverter2D = NULL;
}

VgRoutingModule::VgIRouteRequestParameters* VgMyRoutingHelper::editRoutingRequestParameters()
{
    return &mRoutingRequestParameters;
}

void VgMyRoutingHelper::resetRoutingRequestParameters()
{
    VgRoutingModule::VgIRouteRequestParameters lBase;
    // INSERT HERE any customization to the defaults.
    mRoutingRequestParameters = lBase;
}

void VgMyRoutingHelper::setAvoidStairs(bool pDisabledFriendly)
{
    static const std::string lscAttributes [] =
    {
        "stairs",
        "stairway",
        "escalator"
    };

    const std::string* lStringPtr = lscAttributes;
    const std::string* lEndPtr = lStringPtr + sizeof(lscAttributes)/sizeof(std::string);
    if (pDisabledFriendly)
    {
        for (; lStringPtr < lEndPtr; ++lStringPtr)
        {
            mRoutingRequestParameters.mExcludedAttributes.insert(*lStringPtr);
        }
    }
    else
    {
        for (; lStringPtr < lEndPtr; ++lStringPtr)
        {
            mRoutingRequestParameters.mExcludedAttributes.erase(*lStringPtr);
        }
    }
}

VgEngine::VgRefPtr< VgEngine::VgAnimationDescriptor > VgMyRoutingHelper::getRoutePointHighlightAnimationDescriptor ()
{
    if (!mHighlightedRoutePointsAnimationDescr)
    {
        float lDuration = 2.0;
        mHighlightedRoutePointsAnimationDescr = VgEngine::VgAnimationDescriptor::create();
        mHighlightedRoutePointsAnimationDescr->mLoopMode = VgEngine::VgLoopModes::mscLoop;
        mHighlightedRoutePointsAnimationDescr->mDuration = lDuration;
        mHighlightedRoutePointsAnimationDescr->mCallback = NULL;

        VgEngine::VgRefPtr< VgEngine::VgSinusoidalVectorOffsetFunctorDescriptor > lPosFuncDesc (VgEngine::VgSinusoidalVectorOffsetFunctorDescriptor::create());
        lPosFuncDesc->mStartPhase = -M_PI;
        lPosFuncDesc->mEndPhase = M_PI;
        
        lPosFuncDesc->mBaseVector[0] = 0.0f;
        lPosFuncDesc->mBaseVector[1] = 5.0f;
        lPosFuncDesc->mBaseVector[2] = 0.0f;
        
        lPosFuncDesc->mVector[0] = 0.0f;
        lPosFuncDesc->mVector[1] = 2.5f;
        lPosFuncDesc->mVector[2] = 0.0f;
        
        lPosFuncDesc->mStartTime = 0.0f;
        lPosFuncDesc->mEndTime = lDuration;

        mHighlightedRoutePointsAnimationDescr->mFunctorDescriptors[VgEngine::VgAnimationChannels::mscLocalPositionChannel] = lPosFuncDesc;
    }
    return mHighlightedRoutePointsAnimationDescr;
}

void VgMyRoutingHelper::createAndAddRouteMarker(VgMyRouteCreator::RoutePoint pPoint, const VgEngine::VgPosition& pPosition)
{
    removeRouteMarkers();
    
    if (NULL != mMapModule)
    {
        // Removes previous higlight if exists
        std::map<VgMyRouteCreator::RoutePoint, VgEngine::VgRefPtr< Vg3DModule::VgPoint > >::iterator lItRoutePoint = mHighlightedRoutePoints.find(pPoint);
        if (lItRoutePoint != mHighlightedRoutePoints.end())
        {
            mHighlightedRoutePoints.erase(lItRoutePoint);
        }
        
        std::string lMarkerName = (pPoint == VgMyRouteCreator::eStart) ? "start" : "end";
        
        // Get layer name using position altitude
        std::string lLayerName = getLayerNameForPosition(pPosition);
        
        // Set the altitude which will be the distance of the marker above the floor
        VgEngine::VgPosition lPosition = VgEngine::VgPosition(pPosition);
        lPosition.mZOrAltitude = 7.0;
        
        VgEngine::VgRefPtr< Vg3DModule::VgMarkerDescriptor > lMarker = mTextureLoader->getMarker(lMarkerName);
        if (!lMarker)
        {
            return ;
        }
        
        VgEngine::VgRefPtr< Vg3DModule::VgPoint::Descriptor > lCurrentPoiD  = Vg3DModule::VgPoint::Descriptor::create();
        lCurrentPoiD->mPosition = lPosition;
        lCurrentPoiD->mAltitudeMode = VgEngine::eAbsolute;
        lCurrentPoiD->mGeometryConstantSizeDistance = 100.0f;
        lCurrentPoiD->mVisibilityRampStartVisible = 0.0f;
        lCurrentPoiD->mVisibilityRampFullyVisible = 0.0f;
        lCurrentPoiD->mVisibilityRampStartInvisible = 900.0f;
        lCurrentPoiD->mVisibilityRampFullyInvisible = 1000.0f;
        lCurrentPoiD->mAnchorPosition = VgEngine::eVgBottomCenter;
        lCurrentPoiD->mMarkerDescriptors.push_back(lMarker);
        
        lCurrentPoiD->mDrawOnTop = true;
        
        // Set up a small animation to emphasize the point.
        VgEngine::VgRefPtr< VgEngine::VgAnimationDescriptor > lAnimDescr = getRoutePointHighlightAnimationDescriptor();
        VgEngine::VgRefPtr< VgEngine::VgAnimation > lAnimation = mVgApplication->editEngine()->editInstanceFactory()->instantiate(lAnimDescr);
        VgEngine::VgRefPtr< Vg3DModule::VgPoint > lPoiBasic = mVgApplication->editEngine()->editInstanceFactory()->instantiate(lCurrentPoiD);
        if (!lPoiBasic)
        {
            return ;
        }
        VgEngine::VgRefPtr< VgEngine::VgLayer > lLayer = mVgApplication->editEngine()->editLayerManager()->editLayer(lLayerName);
        if (lLayer.isValid())
        {
            lPoiBasic->setLayer(lLayer);
            lPoiBasic->setAnimation("local",lAnimation);
            lAnimation->start();
        }
        mHighlightedRoutePoints[pPoint] = lPoiBasic;
    }
}


void VgMyRoutingHelper::removeRouteMarkers()
{
    mHighlightedRoutePoints.clear();
}



bool VgMyRoutingHelper::setRoutePoint(VgMyRouteCreator::RoutePoint pPoint, const std::string& pPlaceID)
{
    bool lSuccess = false;
    
    if ( pPlaceID != "" &&
        isPlaceRoutable(pPlaceID))
    {
        
        VgEngine::VgRefPtr<VgRoutingModule::VgIRoutingNode> lRoutingNode = mRouteSolver->getRoutingNode(pPlaceID);
        if (lRoutingNode.isValid())
        {
            mRoutePoints[pPoint] = lRoutingNode;
            
            VgEngine::VgPosition lPos = getPositionOfPlace(pPlaceID);
            createAndAddRouteMarker(pPoint, lPos);
            
            lSuccess = true;
        }
    }
    return lSuccess;
}

bool VgMyRoutingHelper::setRoutePoint(VgMyRouteCreator::RoutePoint pPoint, const VgEngine::VgPosition& pPosition)
{
    bool lSuccess = false;
    
    if (isPositionRoutable(pPosition))
    {
        VgEngine::VgRefPtr<VgRoutingModule::VgIRoutingNode> lRoutingNode = mRouteSolver->getRoutingNode(pPosition);
        
        if(lRoutingNode.isValid())
        {
            mRoutePoints[pPoint] = lRoutingNode;
            
            createAndAddRouteMarker(pPoint, pPosition);
            lSuccess = true;
        }
    }
    return lSuccess;
}

void VgMyRoutingHelper::resetRoutePoint(RoutePoint pPoint)
{
    mRoutePoints.erase(pPoint);
    removeRouteMarkers();
}

bool VgMyRoutingHelper::isRoutePointSet(RoutePoint pPoint)
{
    bool lResult = (mRoutePoints.find(pPoint) != mRoutePoints.end());
    return lResult;
}

void VgMyRoutingHelper::computeRoute()
{
    if(isRoutePointSet(VgMyRouteCreator::eStart) && 
       isRoutePointSet(VgMyRouteCreator::eEnd))
    {            
        requestRoute(mRoutePoints[VgMyRouteCreator::eStart], mRoutePoints[VgMyRouteCreator::eEnd]);
        
        // Reset the route points after use.
        resetRoutePoint(VgMyRouteCreator::eEnd);
        resetRoutePoint(VgMyRouteCreator::eStart);
    }
}

void VgMyRoutingHelper::hide()
{
    if (!mIsRouteVisible)
    {
        return;
    }

    mIsRouteVisible = false;

    // Remove Route Objects
    for (std::vector< LineObject >::iterator lLSIter = mLines.begin();
        lLSIter != mLines.end();
        ++lLSIter )
    {
        if ((*lLSIter).hasBeenAdded == true)
        {
            (*lLSIter).line->setLayer(NULL);
            (*lLSIter).hasBeenAdded = false;
        }
    }
    
    // Remove the POIs.
    for (std::vector< PointObject >::iterator lPoiIter = mPoints.begin();
        lPoiIter != mPoints.end();
        ++lPoiIter )
    {
        (*lPoiIter).point->removeListener((*lPoiIter).callback);
        (*lPoiIter).point->setLayer(NULL);
    }

    for(std::list< VgEngine::VgRefPtr< Vg3DModule::VgLink > >::iterator lItLink = mLinks.begin(), lItEnd = mLinks.end();
        lItLink != lItEnd;
        lItLink++)
    {
        (*lItLink)->setVisible(false);
    }

}

void VgMyRoutingHelper::clear()
{
    hide();
    
    // Do not delete the route inside any VgMyRouteDisplay. 
    //The route object will be deleted byt the Application logic. 
    
    // Delete the LineStrings that have been already removed from the 3D module
    mLines.clear();
    
    // Delete POIs that have that have been already removed from the 3D module
    mPoints.clear();
    
    // Delete links that have that have been already removed from the 3D module
    mLinks.clear();
}


void VgMyRoutingHelper::requestRoute(const VgEngine::VgRefPtr<VgRoutingModule::VgIRoutingNode> pOrigin, const VgEngine::VgRefPtr<VgRoutingModule::VgIRoutingNode> pDestination)
{
    if ( mRoutingModule != NULL )
    {
        if (mRouteSolver == NULL)
        {
            mRouteSolver = mRoutingModule->getRoutingSolver();
        }
        
        if(mRouteSolver)
        {
            // Add route criteria, intialize with our routing request parameters.
            VgRoutingModule::VgIRouteRequestParameters lRouteRequestParams = mRoutingRequestParameters;
            lRouteRequestParams.mCallback = mCallback;

            if (pOrigin.isValid() &&
                pDestination.isValid())
            {
                lRouteRequestParams.mOrigin = pOrigin;
                lRouteRequestParams.mDestinations.push_back(pDestination);
                
                // Request route to be computed
                VgRoutingModule::VgIRouteRequest* lRouteRequest = mRouteSolver->computeRoute(&lRouteRequestParams);
                
                if ( lRouteRequest )
                {
                    delete lRouteRequest;
                }
            }
        }
    }
    
}


bool VgMyRoutingHelper::createRouteObjects(VgEngine::VgConstRefPtr< VgRoutingModule::VgIRoute > const& pRoute)
{
    if (pRoute == NULL)
    {
        return false;
    }

#ifdef DEBUG
        double lLength = pRoute->getLength();
        printf("ROUTE LENGTH: %f\n",lLength);
#endif

    if ( !mRouteConverter2D )
    {
        return false;
    }
    
    // Convert route to vector of VgIRouteGeometryDescriptor's
    std::vector< VgRoutingModule::VgIRouteGeometryDescriptor > lRGDs;
    mRouteConverter2D->convertRoute(pRoute, lRGDs);
    
    bool lFirstLine = true;
    VgEngine::VgPosition lLastPos;
    std::string lLastLayer;
    
    // For each VgIRouteGeometryDescriptor
    std::vector< VgRoutingModule::VgIRouteGeometryDescriptor >::iterator lRGDsIter;
    //int lNbRGDs = lRGDs.size();
    for ( lRGDsIter = lRGDs.begin(); lRGDsIter != lRGDs.end(); ++lRGDsIter )
    {
        VgRoutingModule::VgIRouteGeometryDescriptor lCurrentRGD = (*lRGDsIter);
        
        // Create all line strings
        std::vector< VgEngine::VgRefPtr< Vg3DModule::VgLine::Descriptor > >::iterator lLSDsIter;
        for ( lLSDsIter = lCurrentRGD.mLineDescriptors.begin(); lLSDsIter != lCurrentRGD.mLineDescriptors.end(); ++lLSDsIter )
        {
            // Taylor the line string descriptor to our liking.
            std::vector< VgEngine::VgRefPtr< Vg3DModule::VgLine > > lLines;
            std::vector< VgEngine::VgRefPtr< Vg3DModule::VgPoint > > lPoints;

            VgMyRouteStyler::RouteStyleParameters lStyleParams;
            lStyleParams.mAgentColor = VgEngine::VgColor(1.0,1.0,1.0,1.0);
            lStyleParams.mTrackColor = VgEngine::VgColor(1.0,1.0,1.0,1.0);
            lStyleParams.mTrackBase = mTextureLoader->getTextureBuffer("trackBase");
            lStyleParams.mTrackAgent = mTextureLoader->getTextureBuffer("track");

            mRouteStyler.styleRoute(mRouteStyle, lStyleParams, *lLSDsIter, lLines, lPoints);

            std::vector< VgEngine::VgRefPtr< Vg3DModule::VgLine > >::iterator lLineIter;
            for (lLineIter = lLines.begin(); lLineIter != lLines.end(); ++lLineIter)
            {
                LineObject lLineString;
                lLineString.line = *lLineIter;
                if (lLineString.line.isValid())
                {
                    lLineString.layerName = lCurrentRGD.mLayerName;
                    lLineString.hasBeenAdded = false;
                    mLines.push_back(lLineString); 
                }
            }
            
            std::vector< VgEngine::VgRefPtr< Vg3DModule::VgPoint > >::iterator lPointIter;
            for (lPointIter = lPoints.begin(); lPointIter != lPoints.end(); ++lPointIter)
            {
                PointObject lPoi;
                lPoi.point = *lPointIter;
                lPoi.layerName = lCurrentRGD.mLayerName;
                lPoi.callback = NULL;
                mPoints.push_back(lPoi);
            }
            if (!lFirstLine)
            {
                VgEngine::VgRefPtr< Vg3DModule::VgLink::Descriptor > lLinkDesc = Vg3DModule::VgLink::Descriptor::create();
                lLinkDesc->mTexture = mTextureLoader->getTextureBuffer("track");
                lLinkDesc->mSourcePosition = lLastPos;
                lLinkDesc->mSourcePosition.mZOrAltitude = 0.0f;
                lLinkDesc->mSourcePosition.mSRS = mVgApplication->editEngine()->editLayerManager()->editLayer(lLastLayer)->getSRS();
                lLinkDesc->mSourceColor = VgEngine::VgColor(1.0f,1.0f,1.0f,1.0f);
                lLinkDesc->mTargetPosition = (*lLSDsIter)->mPositions.front();
                lLinkDesc->mTargetPosition.mZOrAltitude = 0.0f;
                lLinkDesc->mTargetPosition.mSRS = mVgApplication->editEngine()->editLayerManager()->editLayer(lCurrentRGD.mLayerName)->getSRS();
                lLinkDesc->mTargetColor = VgEngine::VgColor(1.0f,1.0f,1.0f,1.0f);
                lLinkDesc->mWidth = 10.0f;
                lLinkDesc->mTextureRatio = 1.0f;
                lLinkDesc->mAnimationSpeed = 10.0f;
                VgEngine::VgRefPtr< Vg3DModule::VgLink > lLink = mVgApplication->editEngine()->editInstanceFactory()->instantiate(lLinkDesc);
                if (lLink.isValid())
                {
                    mLinks.push_back(lLink);
                }
            }
            lFirstLine = false;
            lLastLayer = lCurrentRGD.mLayerName;
            lLastPos = (*lLSDsIter)->mPositions.back();
        }
        
        // Create all Pois
        std::vector< VgEngine::VgRefPtr< Vg3DModule::VgPoint::Descriptor > >::iterator lPoiDsIter;
        //int lNbPoiDescriptors = lCurrentRGD.mPointDescriptors.size();
        for ( lPoiDsIter = lCurrentRGD.mPointDescriptors.begin(); lPoiDsIter != lCurrentRGD.mPointDescriptors.end(); ++lPoiDsIter )
        {
            VgEngine::VgRefPtr< VgEngine::VgAnimationDescriptor > lAnimDescr (NULL);
            VgEngine::VgRefPtr< Vg3DModule::VgPoint::Descriptor > lCurrentPoiD = (*lPoiDsIter);
            lCurrentPoiD->mAnchorPosition= VgEngine::eVgBottomCenter;

            VgEngine::VgRefPtr< Vg3DModule::VgIconMarkerDescriptor > lIconMarkerDescr;
            
            // The various POI's can be configured differently.  POI's can have
            // callbacks (this is optional) to allow specific responses to notification 
            // events.  
            // Furthermore, icon images can be configured to provide informative visual feedback.
            VgEngine::VgRefPtr< Vg3DModule::VgIGeometryCallback > lCallback = NULL;
            bool lIsExternalCallback = false;
            
            if ( lPoiDsIter == lCurrentRGD.mPointDescriptors.begin())
            {
                if ( lRGDsIter != lRGDs.begin())
                {
                    // Node Scenario 1: A node that when clicked displays the
                    // previous node in the route.
                    const VgRoutingModule::VgIRouteGeometryDescriptor lPrevRGD = *(lRGDsIter - 1);
                    VgEngine::VgRefPtr< Vg3DModule::VgPoint::Descriptor > lFrontPoiD = lPrevRGD.mPointDescriptors.back();
                    const std::string lLayerPrevName = lPrevRGD.mLayerName;
                    lCallback = new VgMyFloorPoiCallback(mLayerAndCameraHandler, mVgApplication->editEngine()->editCamera(), lFrontPoiD->mPosition, lLayerPrevName);
                    
                    const double lCurrentFloorHeight = computeFloorHeightFromLayer((*lRGDsIter).mLayerName);
                    const double lPrevFloorHeight = computeFloorHeightFromLayer(lLayerPrevName);
                    // We offset buttons coming from "Previous" to the Right, and going to next
                    // to the left to avoid overlapping in certain cases.
                    if ( lPrevFloorHeight == lCurrentFloorHeight)
                    {
                        // Change modality?
                        continue;
                    }
                    else if ( lPrevFloorHeight > lCurrentFloorHeight)
                    {
                        lIconMarkerDescr = mTextureLoader->getMarker("stairsUp");
                        // we offset the stair icons, just in case there are two stairs icon on the same spot.
                        lCurrentPoiD->mAnchorPosition= VgEngine::eVgBottomRight;
                    }
                    else
                    {
                        lIconMarkerDescr = mTextureLoader->getMarker("stairsDown");
                        lCurrentPoiD->mAnchorPosition= VgEngine::eVgTopRight;
                    }
                }
                else
                {
                    // Beginning of the route
                    lIconMarkerDescr = mTextureLoader->getMarker("start");
                    lCurrentPoiD->mAnchorPosition = VgEngine::eVgTopLeft;
                    lAnimDescr = getRoutePointHighlightAnimationDescriptor();
                    // Add the callback if specified.
                    POICallbackMap::iterator lItCallback = mRoutePoiCallbacks.find(kStartPointStrID);
                    if (lItCallback != mRoutePoiCallbacks.end())
                    {
                        lCallback = lItCallback->second;
                        lIsExternalCallback = true;
                    }
                }
            }
            
            else if ( lPoiDsIter == (lCurrentRGD.mPointDescriptors.end() - 1))
            {
                if ( lRGDsIter != (lRGDs.end() - 1))
                {
                    // Node Scenario 2: A node that when clicked displays the next
                    // node in the route.
                    const VgRoutingModule::VgIRouteGeometryDescriptor lNextRGD = *(lRGDsIter + 1);
                    VgEngine::VgRefPtr< Vg3DModule::VgPoint::Descriptor > lBackPoiD = lNextRGD.mPointDescriptors.front();
                    const std::string lLayerNextName = lNextRGD.mLayerName;
                    lCallback = new VgMyFloorPoiCallback(mLayerAndCameraHandler, mVgApplication->editEngine()->editCamera(), lBackPoiD->mPosition, lLayerNextName);

                    const double lCurrentFloorHeight = computeFloorHeightFromLayer((*lRGDsIter).mLayerName);
                    const double lNextFloorHeight = computeFloorHeightFromLayer(lLayerNextName);
                    // Positions for stair images are offsetted to avoid overlapping in case they are on same point.                    
                    // We offset icons to the left, see above explanation.
                    if ( lNextFloorHeight == lCurrentFloorHeight)
                    {
                        // Change modality?
                        continue;
                    }
                    else if ( lNextFloorHeight > lCurrentFloorHeight)
                    {
                        lIconMarkerDescr = mTextureLoader->getMarker("stairsUp");
                        lCurrentPoiD->mAnchorPosition= VgEngine::eVgBottomLeft;
                    }
                    else
                    {
                        lIconMarkerDescr = mTextureLoader->getMarker("stairsDown");
                        lCurrentPoiD->mAnchorPosition= VgEngine::eVgTopRight;
                    }
                }
                else
                {
                    // End of the route
                    lIconMarkerDescr = mTextureLoader->getMarker("end");
                    lAnimDescr = getRoutePointHighlightAnimationDescriptor();
                    lCurrentPoiD->mAnchorPosition = VgEngine::eVgBottomLeft;
                    // Add the callback if specified.
                    POICallbackMap::iterator lItCallback = mRoutePoiCallbacks.find(kEndPointStrID);
                    if (lItCallback != mRoutePoiCallbacks.end())
                    {
                        lCallback = lItCallback->second;
                        lIsExternalCallback = true;
                    }
                }
            }
            else
            {
                // There's a middle node, which are not clickable and not a stair.
                // Currently it does not happen.
            }
            
            if (!lIconMarkerDescr)
            {
                continue;   // If the marker can't be built, continue.
            }

            // To avoid overlapping icons on extruded layers.
            // except that there is too much parallax on the icon
            lCurrentPoiD->mPosition.mZOrAltitude += mObjectHeightOffset;
            lCurrentPoiD->mGeometryConstantSizeDistance = 100.0f;
            lCurrentPoiD->mAltitudeMode = VgEngine::eAbsolute;
            lCurrentPoiD->mVisibilityRampStartVisible = 1.0f;
            lCurrentPoiD->mVisibilityRampFullyVisible = 5.0f;
            lCurrentPoiD->mVisibilityRampStartInvisible = 900.0f;
            lCurrentPoiD->mVisibilityRampFullyInvisible = 1000.0f;
            lCurrentPoiD->mDrawOnTop = true;
            lCurrentPoiD->mMarkerDescriptors.push_back(lIconMarkerDescr);
            
            VgEngine::VgRefPtr< Vg3DModule::VgPoint > lPoiBasic = mInstanceFactory->instantiate(lCurrentPoiD);
            if (lPoiBasic.isValid())
            {
                if (lAnimDescr)
                {
                    VgEngine::VgRefPtr< VgEngine::VgAnimation > lAnim = mInstanceFactory->instantiate(lAnimDescr);
                    lPoiBasic->setAnimation("",lAnim);
                    lAnim->start();
                }
                PointObject lPoi;
                lPoi.point = lPoiBasic;
                lPoi.layerName = lCurrentRGD.mLayerName;
                lPoi.callback = lCallback;
                lPoi.isExternalCallback = lIsExternalCallback;
                
                mPoints.push_back(lPoi);
            }
        }
    }

    return true;
}


void VgMyRoutingHelper::show()
{ 
#ifdef DEBUG
    printf("addObjects: EXISTS pois: %ld lines: %ld\n", mPoints.size(), mLines.size());
#endif // DEBUG
    
    // if objects are already visible or there are no POIs or LineStrings, return
    if (mIsRouteVisible || ((mPoints.size() == 0) && (mLines.size() == 0)))
    {
        return;
    }

    mIsRouteVisible = true;

    unsigned int lPoisAdded = 0, lLinesAdded = 0;
    
    std::vector< LineObject >::iterator lLSIter;
    for ( lLSIter = mLines.begin(); lLSIter != mLines.end(); ++lLSIter )
    {
        if ((*lLSIter).hasBeenAdded == false )
        {
            LineObject& lLine = *lLSIter;
            lLine.line->setLayer(mVgApplication->editEngine()->editLayerManager()->editLayer(lLine.layerName));
            lLine.hasBeenAdded = true;
            lLinesAdded++;
        }
    }
    
    std::vector< PointObject >::iterator lPoiIter;
    for ( lPoiIter = mPoints.begin(); lPoiIter != mPoints.end(); ++lPoiIter )
    {
        // Test if callback is non-null before setting it.
        // Eventhough the engine should interpret it as a no-op, it is better to
        // spare the call.
        if ((*lPoiIter).callback.isValid())
        {
            (*lPoiIter).point->addListener((*lPoiIter).callback);
        }
        (*lPoiIter).point->setLayer(mVgApplication->editEngine()->editLayerManager()->editLayer((*lPoiIter).layerName));
        lPoisAdded++;
    }

    for(std::list< VgEngine::VgRefPtr< Vg3DModule::VgLink > >::iterator lItLink = mLinks.begin(), lItEnd = mLinks.end();
        lItLink != lItEnd;
        lItLink++)
    {
        (*lItLink)->setVisible(true);
    }

#ifdef DEBUG
    printf("addObjects: ADDED pois: %d lines: %d\n", lPoisAdded, lLinesAdded);
#endif
}


double VgMyRoutingHelper::computeFloorHeightFromLayer (const std::string& pLayer) const
{
    double lFloorHeight = 0.0;
  
    VgMapModule::VgIMapModule* lMapModule = (VgMapModule::VgIMapModule*)mVgApplication->editModuleManager()->queryModule("Map");
    if ( lMapModule )
    {
        float pHeightMax;
        float pHeightMin;
        if ( lMapModule->getHeightRangeForLayer(pLayer, pHeightMax, pHeightMin))
        {
            lFloorHeight = ((pHeightMax + pHeightMin) / 2);
        }
    }
    return lFloorHeight;
}


std::string VgMyRoutingHelper::getLayerNameForPosition(VgEngine::VgPosition pPosition)
{
    std::string lLayerName = "";
    
    if(NULL == mMapModule)
    {
        return lLayerName;
    }
    

    mMapModule->getLayerForPosition(pPosition, lLayerName);

    
    return lLayerName;
}

VgEngine::VgPosition VgMyRoutingHelper::getPositionOfPlace(const std::string& pPlaceId)
{
    VgEngine::VgPosition lPos;
    if (NULL == mMapModule) {
        return lPos;
    }
    
    VgMapModule::VgPlaceDescriptor lPlaceDesc;
    mMapModule->queryPlaceDescriptor(pPlaceId, lPlaceDesc);
    
    double lHeight = computeFloorHeightFromLayer(lPlaceDesc.mLayerName);
    lPos = lPlaceDesc.mViewpoint.mPosition;
    lPos.mZOrAltitude = lHeight;
    
    return lPos;
}

void VgMyRoutingHelper::setPoiCallback(const std::string& pIdentifier, VgEngine::VgRefPtr< Vg3DModule::VgIGeometryCallback >const& pCallback)
{
    if (pCallback == NULL)
    {
        mRoutePoiCallbacks.erase(pIdentifier);
    }
    else
    {
        mRoutePoiCallbacks[pIdentifier] = pCallback;
    }
}

bool VgMyRoutingHelper::isPlaceRoutable (const std::string& pID)
{
    if (mRoutingModule != NULL && mRouteSolver == NULL)
    {
        mRouteSolver = mRoutingModule->getRoutingSolver();
    }
    
    if (mRouteSolver == NULL)
    {
        return false;
    }
    
    VgEngine::VgRefPtr<VgRoutingModule::VgIRoutingNode> lRoutingNode = mRouteSolver->getRoutingNode(pID);
    // The node will free itself since it is reference-counted.
    return lRoutingNode.isValid();
}

bool VgMyRoutingHelper::isPositionRoutable (const VgEngine::VgPosition& pPosition)
{
    if (mRoutingModule != NULL && mRouteSolver == NULL)
    {
        mRouteSolver = mRoutingModule->getRoutingSolver();
    }
    
    if (mRouteSolver == NULL)
    {
        return false;
    }
    
    VgEngine::VgRefPtr<VgRoutingModule::VgIRoutingNode> lRoutingNode = mRouteSolver->getRoutingNode(pPosition);
    // The node will free itself since it is reference-counted.
    return lRoutingNode.isValid();
}

bool VgMyRoutingHelper::isVisible()
{
    return mIsRouteVisible;
}

void VgMyRoutingHelper::setRouteStyle (VgMyRouteStyler::RouteStyle pRouteStyle, bool pRecomputeRoute)
{
    mRouteStyle = pRouteStyle;
    if (pRecomputeRoute)
    {
        clear();
        computeRoute();
    }
}

VgMyRouteStyler::RouteStyle VgMyRoutingHelper::getRouteStyle() const
{
    return mRouteStyle;
}

./Common/Src/VgMyStackedLayerAndCameraHandler.cpp

/*
* Copyright 2012, Visioglobe SAS
* ALL RIGHTS RESERVED
*
*
* LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
* distribute, and create derivative works from this Source Code,
* provided that: (1) the user reproduces this entire notice within
* both source and binary format redistributions and any accompanying
* materials such as documentation in printed or electronic format;
* (2) the Source Code is not to be used, or ported or modified for
* use, except in conjunction with Visioglobe SDK; and (3) the
* names of Visioglobe SAS may not be used in any
* advertising or publicity relating to the Source Code without the
* prior written permission of Visioglobe.  No further license or permission
* may be inferred or deemed or construed to exist with regard to the
* Source Code or the code base of which it forms a part. All rights
* not expressly granted are reserved.
*
* This Source Code is provided to Licensee AS IS, without any
* warranty of any kind, either express, implied, or statutory,
* including, but not limited to, any warranty that the Source Code
* will conform to specifications, any implied warranties of
* merchantability, fitness for a particular purpose, and freedom
* from infringement, and any warranty that the documentation will
* conform to the program, or any warranty that the Source Code will
* be error free.
*
* IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
* LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
* ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
* SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
* OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
* PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
* OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
* USE, THE SOURCE CODE.
*
* Contact information:  Visioglobe SAS,
* 300, avenue des papeteries,
* 38190 Villard-Bonnot
* FRANCE
* or:  http://www.visioglobe.com
*/

#include "VgMyStackedLayerAndCameraHandler.h"

#define _USE_MATH_DEFINES
#include <math.h>
#include <time.h>

#ifdef WIN32
#include <float.h>
#define isinf(x)                (!_finite(x))
#endif // WIN32

#include "VgApplication/VgIApplication.h"
#include "VgApplication/VgIManipulatorManager.h"
#include "VgApplication/VgManipulator.h"
#include "VgApplication/VgSimpleGestureManipulator.h"

#include "VgEngine/VgLayerManager.h"
#include "VgEngine/VgLayer.h"
#include "VgEngine/VgICamera.h"
#include "VgEngine/VgPosition.h"
#include "VgEngine/VgAnimation.h"
#include "VgEngine/VgVectorInterpolationFunctorDescriptor.h"
#include "VgEngine/VgQuaternionInterpolationFunctorDescriptor.h"
#include "VgEngine/VgAxialRotationQuaternionFunctorDescriptor.h"
#include "VgEngine/VgSpatial.h"
#include "VgEngine/VgIAnimationManager.h"
#include "VgEngine/VgAnimation.h"
#include "VgEngine/VgIAnimationCallback.h"
#include "VgEngine/VgPositionToolbox.h"
#include "VgEngine/VgRefPtr.h"
#include "VgEngine/VgReferenced.h"
#include "VgEngine/VgIDatabase.h"
#include "VgEngine/VgInstanceFactory.h"
#include "VgEngine/VgSplineOrientationQuaternionFunctorDescriptor.h"
#include "VgEngine/VgSplineVectorFunctorDescriptor.h"
#include "VgEngine/VgTypes.h"

#include "VgMyLayerAndCameraListener.h"



class StopAnimationCallback : public VgEngine::VgIAnimationCallback
{

public:

    StopAnimationCallback(VgEngine::VgRefPtr< VgEngine::VgSpatial > pSpatial, VgApplication::VgIManipulatorManager* pManipMgr, VgMyStackedLayerAndCameraHandler* pSelector)
        : mManipMgr(pManipMgr)
        , mSelector(pSelector)
    {}

    void onFinish (VgEngine::VgRefPtr< VgEngine::VgAnimation > pAnimation)
    {
        pAnimation->stop();
        
        if (mSelector != NULL)
        {
            mSelector->updateManipulatorForGlobalView(mSelector->isGlobalView());
        }
    }

protected:

    VgApplication::VgIManipulatorManager* mManipMgr;

    VgMyStackedLayerAndCameraHandler* mSelector;

};

class LayerHideCallback : public VgEngine::VgIAnimationCallback
{

public:

    inline LayerHideCallback(VgEngine::VgIEngine* pEngine, VgEngine::UInt pLayerIndex)
        : mEngine(pEngine)
        , mLayerIndex(pLayerIndex)
    {}

    void onFinish (VgEngine::VgRefPtr< VgEngine::VgAnimation > pAnimation)
    {
        pAnimation->stop();
        VgEngine::VgLayerManager::LayerList& lLayers = mEngine->editLayerManager()->editLayers();
        if (mLayerIndex < lLayers.size())
        {
            VgEngine::VgRefPtr< VgEngine::VgLayer > lLayer = lLayers[mLayerIndex];
            lLayer->setVisible(false);
            lLayer->setHostedVisible(false);
        }
    }

protected:

    VgEngine::VgIEngine* mEngine;

    VgEngine::UInt mLayerIndex;

};

FloorSelectorManipulator::FloorSelectorManipulator(VgApplication::VgIApplication* pApplication, VgMyStackedLayerAndCameraHandler* pSelector, unsigned int pViewWidthInPixels, unsigned int pViewHeightInPixels)
    : mSelector(pSelector)
    , mApplication(pApplication)
    , mDragTotalOffsetY(0)
    , mDragGestureStarted(false)
    , mPinchGestureStarted(false)
    , mOriginalSpan(0)
{
    mViewSize[0] = pViewWidthInPixels;
    mViewSize[1] = pViewHeightInPixels;
}

FloorSelectorManipulator::~FloorSelectorManipulator()
{}

void FloorSelectorManipulator::onDoubleClick (float x, float y)
{
}


// Implements, single click on middle third screen to switch to detailed view.
void FloorSelectorManipulator::onClick (float x, float y)
{
    if (y < 0.33f)
    {
        mSelector->gotoLayer(mSelector->getCurrentLayerIndex()+1);
        
    }
    else if (y > 0.66f)
    {
        mSelector->gotoLayer(mSelector->getCurrentLayerIndex()-1);
    }
    else
    {
        // and middle third of screen.
        mSelector->switchToDetailedView();
    }
}

void FloorSelectorManipulator::onSimplePinch(const VgEngine::VgGestureState pState, const float pSpan, const float pVelocity)
{
    //printf("PINCH : STATE  : %i, current Span : %.2f, velocity : %.2f\n", (int)pState, pSpan, pVelocity);
    if (mDragGestureStarted)
    {
        cancelDragGesture();
        return;
    }

    if (pState == VgEngine::eVgGestureEnd)
    {
        cancelPinchGesture();
        return;
    }

    if (pState == VgEngine::eVgGestureBegin)
    {
        mPinchGestureStarted = true;
        mOriginalSpan = pSpan;
    }

    if (!mPinchGestureStarted)
    {
        return ;
    }

    const float lMaxSpanValue = (float) std::max(mViewSize[0], mViewSize[1]);

    const float lSpanDiff = mOriginalSpan - pSpan;

    // Zoom-in/out a little
    const VgEngine::VgPositionToolbox* lToolbox = mApplication->editEngine()->getPositionToolbox();
    VgEngine::VgICamera* lCamera = mApplication->editEngine()->editCamera();
    
    VgEngine::VgPosition lStackCenter = mSelector->getStackCenter();
    
    VgEngine::VgPosition lOriginalPos = lToolbox->offsetPosition(lStackCenter,
                                                                 lCamera->getHeading(),
                                                                 lCamera->getPitch(),
                                                                 -mSelector->getParam(VgMyStackedLayerAndCameraHandler::eStackViewDistance) );
    
    VgEngine::VgPosition lEndPos = lToolbox->offsetPosition(lOriginalPos,
                                                            lCamera->getHeading(),
                                                            lCamera->getPitch(),
                                                            -mSelector->getParam(VgMyStackedLayerAndCameraHandler::eStackViewDistance) * 0.75f * lSpanDiff / lMaxSpanValue);
    lCamera->setPosition(lEndPos);
}

void FloorSelectorManipulator::onSimpleDrag(const VgEngine::VgGestureState pState, const unsigned int pNbTouch, const float pAverageXOffset, const float pAverageYOffset)
{
    //printf("DRAG : STATE : %i, NbTouch : %i, Offset %.2f,%.2f\n", (int)pState,  pNbTouch, pAverageXOffset, pAverageYOffset);

    if (pNbTouch != 1)  // In this case, it reacts only to single finger drags.
    {
        return;
    }

    if (mPinchGestureStarted)
    {
        cancelPinchGesture();
        return;
    }

    if (pState == VgEngine::eVgGestureEnd)
    {
        cancelDragGesture();
        return;
    }

    if (pState == VgEngine::eVgGestureBegin)
    {
        mDragGestureStarted = true;
    }

    if (!mDragGestureStarted)
    {
        return;
    }

    mDragTotalOffsetY += (int)pAverageYOffset;

    const unsigned int lCurrentLayer = mSelector->getCurrentLayerIndex();

    const bool lIsManipulatingUpperLayer = (mDragTotalOffsetY < 0.f);
    const unsigned int lFloorToMove = lIsManipulatingUpperLayer ? lCurrentLayer + 1 : lCurrentLayer - 1;
    bool lIsExtremityLayer = false;
    VgEngine::VgLayerManager::LayerList& lLayerList = mApplication->editEngine()->editLayerManager()->editLayers();
    if (lFloorToMove >= lLayerList.size())
    {
        lIsExtremityLayer = true;
    }
    
    const float lDragDistanceThreshold = (float)(mViewSize[1] * mSelector->getParam(VgMyStackedLayerAndCameraHandler::eChangeLayerTriggerThreshold));

    // Change to the next floor if available once the user's drag enough 
    if (!lIsExtremityLayer && fabsf((float)mDragTotalOffsetY) > lDragDistanceThreshold)
    {
        // We can drag through multiple floors. so no resetting mDragGestureStarted
        mSelector->gotoLayer(lFloorToMove);
        mDragTotalOffsetY = 0;
        return;
    }
    
    // Move the layers while the user is dragging.
    const float lcOffsetRatio = mViewSize[1] * 0.2f; // This Ratio determines how quickly the map moves given a drag offset. 
    const float lOffset = (float) mSelector->getParam(VgMyStackedLayerAndCameraHandler::eLayerDistance) * pAverageYOffset / lcOffsetRatio;

    for (int iFloorIndex = lLayerList.size() - 1; iFloorIndex >= 0; --iFloorIndex)
    {
        VgEngine::VgRefPtr< VgEngine::VgLayer > lLayerToMove = lLayerList[iFloorIndex];
        VgEngine::VgPosition lCurrentFloorPosition = lLayerToMove->getPosition();
        
        lCurrentFloorPosition.mZOrAltitude += lOffset;
        lLayerToMove->setPosition(lCurrentFloorPosition);
    }
}

void FloorSelectorManipulator::setViewSize(unsigned int pWidth, unsigned int pHeight)
{
    mViewSize[0] = pWidth;
    mViewSize[1] = pHeight;
}

void FloorSelectorManipulator::cancelDragGesture()
{
    if (mDragGestureStarted && mDragTotalOffsetY != 0)
    {
        // If we drag through multiple layers, we need to animate back to the current position.
        // we cannot use gotoLayer, because it might make the stack "jump"
        mSelector->animateLayersFromCloseToStackView(VgMyStackedLayerAndCameraHandler::eFromGlobalToGlobaView, (float) mSelector->getParam(VgMyStackedLayerAndCameraHandler::eAnimateCancelDragDuration), true);
    }

    mDragTotalOffsetY = 0;
    mDragGestureStarted = false;
}

void FloorSelectorManipulator::cancelPinchGesture() {
    if (mPinchGestureStarted)
    {
        // Animate to the stacked multi layer view
        VgEngine::VgIViewPoint lViewPoint = mSelector->getStackViewPoint();
        mSelector->animateCameraToViewPoint(lViewPoint , (float) mSelector->getParam(VgMyStackedLayerAndCameraHandler::eAnimateCancelPinchDuration), true);
    }

    mPinchGestureStarted = false;
}

VgMyStackedLayerAndCameraHandler::VgMyStackedLayerAndCameraHandler(VgApplication::VgIApplication* pVgApplication, VgMyLayerAndCameraListener* pListener, unsigned int pViewWidthInPixels, unsigned int pViewHeightInPixels)
: mVgApplication(pVgApplication)
, mLayerUpdateListener(pListener)
, mCurrentLayerIndex(0)
, mIsLayerStackDisplayed(false)
, mIsViewModeInitialized(false)
{
    // Register a VgEngine::VgISimpleGestureManipulatorListener to customize the gestures handling.
    VgApplication::VgSimpleGestureManipulator* lSimpleGestureManipulator = 
        static_cast<VgApplication::VgSimpleGestureManipulator*>(mVgApplication->editManipulatorManager()->editManipulatorObject("simpleGesture"));
    mManipulatorListener = new FloorSelectorManipulator(mVgApplication, this, pViewWidthInPixels, pViewHeightInPixels);
    lSimpleGestureManipulator->setListener(mManipulatorListener);

    setDefaultStackParams();
    
    refreshParameters(pViewWidthInPixels, pViewHeightInPixels);

    mCameraCallback = NULL;

    VgEngine::VgLayerManager::LayerList& lLayers = mVgApplication->editEngine()->editLayerManager()->editLayers();
    mLayersCallback.assign(lLayers.size(), NULL);
    
    // Store original LOD and load factors
    VgEngine::VgLayerManager::LayerList::iterator lIter = lLayers.begin();
    for (unsigned int i=0; i<lLayers.size() && lIter != lLayers.end(); ++lIter, ++i)
    {
        VgEngine::VgRefPtr< VgEngine::VgLayer > lLayer = (*lIter);
        mLoadFactors[lLayer->getName()] = lLayer->getLoadFactor();
        mLODsFactors[lLayer->getName()] = lLayer->getLODFactor();
    }
    
    // Store the original camera view.
    mCamStartViewPoint = mVgApplication->editEngine()->editCamera()->getViewpoint();
}

VgMyStackedLayerAndCameraHandler::~VgMyStackedLayerAndCameraHandler()
{
    VgApplication::VgSimpleGestureManipulator* lSimpleGestureManipulator = static_cast<VgApplication::VgSimpleGestureManipulator*>(mVgApplication->editManipulatorManager()->editManipulatorObject("simpleGesture"));
    lSimpleGestureManipulator->setListener(NULL);

    // Make sure no pending animations are called.
    mVgApplication->editEngine()->editAnimationManager()->setCameraAnimation(NULL);

    mLayersCallback.clear();
    
    mLODsFactors.clear();
    mLoadFactors.clear();
}


void VgMyStackedLayerAndCameraHandler::setDefaultStackParams()
{
    // Default stack center position is the root of the scene.
    VgEngine::VgPosition lStackCenterPos( mVgApplication->editEngine()->getPositionToolbox()->getSceneSRS() );
    
    float lDatasetSize = 700.0; // Default stack size that works well for map generic.
    
    // Calculate the stack center based on the dataset limits within vg_config.xml
    const VgEngine::VgIDatabaseDatasetDescriptor* lDescriptor = mVgApplication->editEngine()->editDatabase()->getCurrentDatasetDescriptor();
    if(NULL != lDescriptor)
    {
        // Calculate real stack diameter
        float lDatasetSizeTemp = (float) mVgApplication->editEngine()->getPositionToolbox()->computeDistance(lDescriptor->mMinimum, lDescriptor->mMaximum);
        // If the dataset limits have been set correctly in the configuration file
        if (lDatasetSizeTemp > 1e-3)
        {
            // Then update the dataset size
            lDatasetSize = lDatasetSizeTemp;
            lStackCenterPos.mSRS = lDescriptor->mMinimum.mSRS;
            // And the stack center by default should be in the center of the dataset limits.
            lStackCenterPos.mXOrLongitude = (lDescriptor->mMinimum.mXOrLongitude + lDescriptor->mMaximum.mXOrLongitude) / 2;
            lStackCenterPos.mYOrLatitude = (lDescriptor->mMinimum.mYOrLatitude + lDescriptor->mMaximum.mYOrLatitude) / 2;
            lStackCenterPos.mZOrAltitude = (lDescriptor->mMinimum.mZOrAltitude + lDescriptor->mMaximum.mZOrAltitude) / 2;
        }
    }
    
    setParam(eLayerMaxSize, lDatasetSize);
    setStackCenterPosition(lStackCenterPos);
    
    setParam(eFarAwayHeight, 1000);
    
    // Set the default heading to be that from the initial camera view (taken
    // from the configuration file)
    float lStackViewHeading = mVgApplication->editEngine()->editCamera()->getViewpoint().mHeading;
    setParam(eStackViewHeading, lStackViewHeading);
    setParam(eStackViewPitch, -30);
    
    setParam(eChangeLayerTriggerThreshold, 0.1);
    
    setParam(eAnimateToDetailCameraDuration, 1.0);
    setParam(eAnimateToGlobalCameraDuration, 1.5);
    setParam(eAnimateToGlobalLayerDuration, 1.5);
    setParam(eAnimateToDetailLayerDuration, 1.0);
    setParam(eAnimateChangeOfLayerDuration, 0.5);
    setParam(eAnimateCancelPinchDuration, 0.3);
    setParam(eAnimateCancelDragDuration, 0.3);

    setParam(eAnimateMaxViewPointDuration, 3.0);
    
    setParam(eStackActiveLayerAngle,0.0f);
    setParam(eStackNonActiveLayerAngle,0.0f);
    
}

void VgMyStackedLayerAndCameraHandler::updateManipulatorForGlobalView(bool pIsGlobalView)
{
    if (pIsGlobalView)
    {
        mVgApplication->editManipulatorManager()->selectManipulator("simpleGesture");
        onSelectorReady();
    }
    else
    {
        mVgApplication->editManipulatorManager()->selectManipulator("2D");
        //mVgApplication->editManipulatorManager()->selectManipulator("simpleTrackball");
        onLayerSelected();
    }
    
    if (mLayerUpdateListener)
    {
        bool lDoesChangeFromGlobalToDetailed = !pIsGlobalView;
        mLayerUpdateListener->viewDidChange(this, lDoesChangeFromGlobalToDetailed);
    }
}

bool VgMyStackedLayerAndCameraHandler::isGlobalView()
{
    return mIsLayerStackDisplayed;
}


void VgMyStackedLayerAndCameraHandler::switchToGlobalView(bool pIsAnimated)
{
    if (mIsLayerStackDisplayed && mIsViewModeInitialized)
    {
        //printf("******** switchToGlobalView skipping because %d %d", mIsLayerStackDisplayed,mIsViewModeInitialized);
        return;
    }
    
    if (mLayerUpdateListener)
    {
        mLayerUpdateListener->viewWillChange(this, false);
    }

    // Store the current camera view. It will be restored when leaving the stack view.
    // REQUIREMENT: Orientation floor level same as orientation global view, set to false
    bool lSaveDetailedViewpoint = false;
    if (lSaveDetailedViewpoint)
    {
        mCamStartViewPoint = mVgApplication->editEngine()->editCamera()->getViewpoint();
    }

    VgEngine::VgIViewPoint lViewPoint = getStackViewPoint();
    animateCameraToViewPoint(lViewPoint, (float)getParam(eAnimateToGlobalCameraDuration), pIsAnimated);
    
    animateLayersFromCloseToStackView(eFromDetailedToStackView, (float)getParam(eAnimateToGlobalLayerDuration), pIsAnimated);
    
    if(!pIsAnimated)
    {
        updateManipulatorForGlobalView(true);
    }
    
    if (!mIsViewModeInitialized)
    {
        mIsViewModeInitialized = true;
    }
    
    mIsLayerStackDisplayed = true;
}


void VgMyStackedLayerAndCameraHandler::switchToDetailedView(bool pIsAnimated)
{
    if ((!mIsLayerStackDisplayed) && mIsViewModeInitialized)
    {
        return;
    }
    
    if (mLayerUpdateListener)
    {
        mLayerUpdateListener->viewWillChange(this, true);
    }

    // Note : camera animation length must be <= layer animation length due to the manipulator change at the end of layers animation.
    animateCameraToViewPoint(mCamStartViewPoint, (float) getParam(eAnimateToDetailCameraDuration), pIsAnimated);
    
    animateLayersFromCloseToStackView(eFromStackToDetailedView, (float) getParam(eAnimateToDetailLayerDuration), pIsAnimated);

    if(!pIsAnimated)
    {
        updateManipulatorForGlobalView(false);
    }
    
    if (!mIsViewModeInitialized)
    {
        mIsViewModeInitialized = true;
    }
    
    mIsLayerStackDisplayed = false;
}


const std::string& VgMyStackedLayerAndCameraHandler::getFocusedLayerName()
{
    VgEngine::VgLayerManager::LayerList& lLayers = mVgApplication->editEngine()->editLayerManager()->editLayers();
    return lLayers[mCurrentLayerIndex]->getName();
}


unsigned int VgMyStackedLayerAndCameraHandler::getNumberOfLayers()
{
    VgEngine::VgLayerManager::LayerList& lLayers = mVgApplication->editEngine()->editLayerManager()->editLayers();
    return lLayers.size();
}


bool VgMyStackedLayerAndCameraHandler::getLayerName(const unsigned int pLayerIndex, std::string& pLayerNameOut)
{
    VgEngine::VgLayerManager::LayerList& lLayers = mVgApplication->editEngine()->editLayerManager()->editLayers();
    if (pLayerIndex < lLayers.size())
    {
        pLayerNameOut = lLayers[pLayerIndex]->getName();
        return true;
    }
    else
    {
        return false;
    }
}


void VgMyStackedLayerAndCameraHandler::gotoLayer(const std::string& pLayerName, bool pIsAnimated)
{
    VgEngine::VgLayerManager::LayerList& lLayers = mVgApplication->editEngine()->editLayerManager()->editLayers();
    VgEngine::VgLayerManager::LayerList::const_iterator lItLayer = lLayers.begin(), lItEnd = lLayers.end();
    bool lIsFound = false;
    unsigned int lLayerIndex = 0;
    while (!lIsFound && lItLayer != lItEnd)
    {
        if ((*lItLayer)->getName() == pLayerName)
        {
            lIsFound = true;
        }
        else
        {
            lItLayer++;
            lLayerIndex++;
        }
    }
    
    if (lIsFound)
    {
        gotoLayer(lLayerIndex, pIsAnimated);
    }
}


void VgMyStackedLayerAndCameraHandler::gotoLayer(const unsigned int pLayerIndex, bool pIsAnimated)
{
    VgEngine::VgLayerManager::LayerList& lLayers = mVgApplication->editEngine()->editLayerManager()->editLayers();
    if (pLayerIndex >= lLayers.size() || pLayerIndex == mCurrentLayerIndex)
    {
        return;
    }

    if (mLayerUpdateListener)
    {
        mLayerUpdateListener->layerWillChangeFrom(this, lLayers[mCurrentLayerIndex]->getName(), lLayers[pLayerIndex]->getName());
    }

    if (mIsLayerStackDisplayed)
    {
        gotoLayerInGlobalView(pLayerIndex, pIsAnimated);
    }
    else
    {
        gotoLayerInDetailedView(pLayerIndex, pIsAnimated);
    }

    mPreviousLayerIndex = mCurrentLayerIndex;
    mCurrentLayerIndex = pLayerIndex;
}

void VgMyStackedLayerAndCameraHandler::gotoLayerInGlobalView(const unsigned int pLayerIndex, bool pIsAnimated)
{
    if (mIsLayerStackDisplayed)
    {
        VgEngine::VgLayerManager::LayerList& lLayers = mVgApplication->editEngine()->editLayerManager()->editLayers();
        if (pLayerIndex >= lLayers.size() || pLayerIndex == mCurrentLayerIndex)
        {
            return;
        }
        // Animates each layer to it's new position
        VgEngine::VgLayerManager::LayerList::iterator lIter = lLayers.begin();
        VgEngine::VgPosition lLayerStartPos;
        
        VgEngine::VgRefPtr< VgEngine::VgIAnimationCallback > lAnimCallback = NULL;
        VgEngine::VgPosition lLayerEndPos;
    
        // All layers are already visible. Moves layers so that pLayerIndex is centered on the view.
        for (unsigned int iLayer=0; iLayer<lLayers.size() && lIter != lLayers.end(); ++lIter, ++iLayer)
        {
            VgEngine::VgRefPtr< VgEngine::VgLayer > lLayer = (*lIter);
            float lStartAngle = getParam(eStackNonActiveLayerAngle);
            float lEndAngle = getParam(eStackNonActiveLayerAngle);
            
            lLayerStartPos = lLayer->getPosition();
            
            bool lIsHostVisibleForLayer = false;
            if(iLayer == pLayerIndex)
            {
                lIsHostVisibleForLayer = true;
                lEndAngle = getParam(eStackActiveLayerAngle);
            }
            if (iLayer == mCurrentLayerIndex)
            {
                lStartAngle = getParam(eStackActiveLayerAngle);
                lEndAngle = getParam(eStackNonActiveLayerAngle);
            }
            if (mCurrentLayerIndex == pLayerIndex)
            {
                lStartAngle = lEndAngle = getParam(eStackActiveLayerAngle);
            }
            
            lLayer->setHostedVisible(lIsHostVisibleForLayer);
            
            lLayer->setVisible(true);
            
            // Note: pLayerIndex will eventually be the current layer.
            lLayerEndPos = getPositionForLayerInGlobalView(iLayer, pLayerIndex);
            
            if (pIsAnimated)
            {
                lAnimCallback = registerCallback(VgEngine::VgRefPtr<StopAnimationCallback>(new StopAnimationCallback((*lIter), NULL, NULL)), iLayer);
                animateLayerToPositionAndRotation(lLayer, lLayerStartPos, lLayerEndPos, lAnimCallback, (float)getParam(eAnimateChangeOfLayerDuration),lStartAngle,lEndAngle);
            }
            else
            {
                lLayer->setPosition(lLayerEndPos);
            }
        }
    }
}


void VgMyStackedLayerAndCameraHandler::gotoLayerInDetailedView(const unsigned int pLayerIndex, bool pIsAnimated)
{
    if(!mIsLayerStackDisplayed)
    {
        VgEngine::VgLayerManager::LayerList& lLayers = mVgApplication->editEngine()->editLayerManager()->editLayers();
        
        VgEngine::VgPosition lLayerStartPos;
        VgEngine::VgRefPtr< VgEngine::VgIAnimationCallback > lAnimCallback = NULL;
        
        VgEngine::VgPosition lLayerEndPos;
        
        // Only the current layer is visible.
        // Set visible all layers between the current one and the target.
        for (unsigned int iLayer =std::min(mCurrentLayerIndex,pLayerIndex), iLayerEnd = std::max(mCurrentLayerIndex,pLayerIndex)  ; iLayer<=iLayerEnd ; ++iLayer)
        {
            VgEngine::VgRefPtr< VgEngine::VgLayer > lLayer = lLayers[iLayer];
            lLayerStartPos = lLayer->getPosition();
            
            if (((iLayer < pLayerIndex && iLayer >= mCurrentLayerIndex) || (iLayer > pLayerIndex && iLayer <= mCurrentLayerIndex)))
            {
                lLayer->setVisible(true);
                lLayer->setHostedVisible(false);
                
                if (pIsAnimated)
                {
                    lAnimCallback = registerCallback(VgEngine::VgRefPtr< LayerHideCallback>(new LayerHideCallback(mVgApplication->editEngine(), iLayer)), iLayer);
                }
            }
            // no else here. Other layers are already hidden.
            
            if (iLayer != pLayerIndex)
            {
                lLayer->setLODFactor(1e-3f);
                lLayer->setLoadFactor(1e-3f);
            }
            else
            {
                lLayer->setVisible(true);
                lLayer->setHostedVisible(true);
                
                lLayer->setLODFactor(mLODsFactors[lLayer->getName()]);
                lLayer->setLoadFactor(mLoadFactors[lLayer->getName()]);
                
                if (pIsAnimated)
                {
                    lAnimCallback = registerCallback(VgEngine::VgRefPtr< StopAnimationCallback >(new StopAnimationCallback(lLayer, NULL, NULL)), iLayer);
                }
            }
            
            // Note: pLayerIndex will eventually be the current layer.
            lLayerEndPos = getPositionForLayerInDetailedView(iLayer, pLayerIndex);

            if (pIsAnimated)
            {
                animateLayerToPositionAndRotation(lLayer, lLayerStartPos, lLayerEndPos, lAnimCallback, (float) getParam(eAnimateChangeOfLayerDuration), 0.0f,60.0f);
            }
            else
            {
                if (iLayer == pLayerIndex)
                {
                    lLayer->setPosition(lLayerEndPos);
                }
                else
                {
                    lLayer->setVisible(false);
                    lLayer->setHostedVisible(false);
                }       
            }
        }
    }
}

VgEngine::VgPosition VgMyStackedLayerAndCameraHandler::getPositionForLayerInGlobalView(unsigned int pLayerIndex, unsigned int pFocusedLayer)
{
    VgEngine::VgPosition lLayerPos(mVgApplication->editEngine()->getPositionToolbox()->getSceneSRS());
    
    // The distance from the focused layer.
    float lZDistanceFromFocusedLayer = 0.0f;
    
    if (pLayerIndex != pFocusedLayer)
    {
         lZDistanceFromFocusedLayer = getParam(eLayerDistanceFromCurrent) + (getParam(eLayerDistance) * ( abs((float)pLayerIndex - (float)pFocusedLayer) - 1.0f) );
        
        if(pLayerIndex > pFocusedLayer)
        {
            
            // Move the layer away from the focused layer, in a direction perpendicular to the camera, starting from the stack center
            float lHeading = getParam(eStackViewHeading)+180.0f;
            float lPitch = -(getParam(eStackViewPitch)+90.0f);
            lLayerPos = mVgApplication->editEngine()->getPositionToolbox()->offsetPosition(lLayerPos, lHeading, lPitch, -lZDistanceFromFocusedLayer);
        }
        else
        {
            lLayerPos.mZOrAltitude = -lZDistanceFromFocusedLayer;
        }
    }
    else
    {
        lLayerPos.mZOrAltitude = lZDistanceFromFocusedLayer;
    }
    
    return lLayerPos;
}


VgEngine::VgPosition VgMyStackedLayerAndCameraHandler::getPositionForLayerInDetailedView(unsigned int pLayerIndex, unsigned int pFocusedLayer)
{   
    // Create the scene root position
    VgEngine::VgPosition lSceneRoot( mVgApplication->editEngine()->getPositionToolbox()->getSceneSRS() );
    
    // Set the layer to the scene root position
    VgEngine::VgPosition lLayerPos = lSceneRoot;
    
    // Update the altitude in relation to the layer.
    if (pLayerIndex != pFocusedLayer)
    {
        lLayerPos.mZOrAltitude = pLayerIndex < pFocusedLayer ? -getParam(eFarAwayHeight) : getParam(eFarAwayHeight);
    }
    else
    {
        lLayerPos.mZOrAltitude = 0;
    }
    return lLayerPos;
}



void VgMyStackedLayerAndCameraHandler::gotoViewpoint(const VgEngine::VgIViewPoint& pViewPoint, const std::string& pLayerName, bool pIsAnimated)
{
    // Chaining animations currently not implmented.  Thus, gotoLayer isn't
    // animated, regardless of the pIsAnimated argument
    
    // If global view
    if(isGlobalView())
    {
        gotoLayer(pLayerName, pIsAnimated);
    }
    // Else detailed view
    else
    {
        VgEngine::VgRefPtr< VgEngine::VgLayer > lCurrentLayer = mVgApplication->editEngine()->editLayerManager()->editLayers().at( getCurrentLayerIndex() );
        std::string lCurrentLayerName = lCurrentLayer->getName();
        
        const VgEngine::VgPositionToolbox* lPositionToolbox = mVgApplication->editEngine()->getPositionToolbox();
        
        if (lPositionToolbox->computeDistance(pViewPoint.mPosition, mVgApplication->editEngine()->editCamera()->getPosition()) < 1e-3)
        {
            if (lCurrentLayerName != pLayerName || !mIsViewModeInitialized)
            {
                gotoLayer(pLayerName, pIsAnimated);
            }
        }
        else
        {
            // Compute the duration.
            std::vector<VgEngine::VgPosition> lPosVec;
            lPosVec.push_back(pViewPoint.mPosition);
            lPosVec.push_back(mVgApplication->editEngine()->editCamera()->getPosition());
            
            const double lRouteLength = lPositionToolbox->computeDistance(lPosVec);
            double lSpeed = 10.0;
            double lDuration = std::min((lRouteLength / lSpeed), getParam(eAnimateMaxViewPointDuration));
            
            
            // The layer is the current layer
            if(lCurrentLayerName == pLayerName && mIsViewModeInitialized)
            {
                // Animate to view point.
                animateCameraToViewPoint(pViewPoint, (float)lDuration, pIsAnimated);
            }
            // Else, need to change to the layer
            else
            {
                // Update camera (no animation)
                animateCameraToViewPoint(pViewPoint, (float)lDuration, false);
                // Animated to layer
                gotoLayer(pLayerName, pIsAnimated);
            }
        }
    }
}



void VgMyStackedLayerAndCameraHandler::gotoLookAtPosition(const VgEngine::VgPosition& pPosition, const std::string& pLayerName, bool pIsAnimated)
{
    VgEngine::VgRefPtr< VgEngine::VgLayer > lLayer = mVgApplication->editEngine()->editLayerManager()->editLayer(pLayerName);
    if (!lLayer)
    {
        return;
    }
    
    VgEngine::VgICamera* lCamera = mVgApplication->editEngine()->editCamera();
    const VgEngine::VgPositionToolbox* lPositionToolbox = mVgApplication->editEngine()->getPositionToolbox();
    
    VgEngine::VgPosition lNewPosition = pPosition;
    // We must be sure that the final position is expressed in the Scene SRS.
    lPositionToolbox->convert(lNewPosition, lCamera->getPosition().mSRS);
    lNewPosition.mZOrAltitude = 0.0;
    
    std::vector< VgEngine::VgPosition > lPositions;
    lPositions.push_back(lNewPosition);
    VgEngine::VgIViewPoint lViewPointEnd = lCamera->getViewpointFromPositions(lPositions, 0, 0, 0, 0);

    gotoViewpoint(lViewPointEnd, pLayerName, pIsAnimated);
}

void VgMyStackedLayerAndCameraHandler::animateLayersFromCloseToStackView(eFromToViewEnum pDirection, float pDuration, bool pIsAnimated )
{
    // we want pFromCloseToStackView to be:
    // true:  eFromDetailedToStackView,
    // true:  eFromGlobalToGlobaView // Used by cancel drag.
    // false: eFromStackToDetailedView
    bool pFromCloseToStackView = (pDirection != eFromStackToDetailedView) ? true : false;
    VgEngine::VgLayerManager::LayerList lLayers = mVgApplication->editEngine()->editLayerManager()->editLayers();
    VgEngine::VgLayerManager::LayerList::iterator lIter = lLayers.begin();

    VgEngine::VgPosition lLayerStartPos;
    VgEngine::VgPosition lLayerEndPos;
    for (unsigned int i=0; i<lLayers.size() && lIter != lLayers.end(); ++lIter, ++i)
    {
        VgEngine::VgRefPtr< VgEngine::VgLayer > lLayer = (*lIter);

        VgEngine::VgRefPtr< VgEngine::VgIAnimationCallback > lCallback = NULL;
        lLayerStartPos = lLayer->getPosition();
        
        if (!mIsLayerStackDisplayed)
        {
            lLayer->setLODFactor(1e-3f);
            lLayer->setLoadFactor(1e-3f);
            lLayer->setVisible(true);
        }
        else if (pFromCloseToStackView)
        {
            if (pIsAnimated)
            {
                lCallback = registerCallback(VgEngine::VgRefPtr< StopAnimationCallback >(new StopAnimationCallback(lLayer, NULL, NULL)), i);
            }
        }
        
        if (i != mCurrentLayerIndex)
        {
            lLayer->setHostedVisible(false);
            
            if (pFromCloseToStackView)
            {
                if (!mIsLayerStackDisplayed)
                {
                    if (pIsAnimated)
                    {
                        lCallback = registerCallback(VgEngine::VgRefPtr< StopAnimationCallback >(new StopAnimationCallback(lLayer, NULL, NULL)), i);
                    }
                }
            }
            else
            {
                if (pIsAnimated)
                {
                    lCallback = registerCallback(VgEngine::VgRefPtr< LayerHideCallback >(new LayerHideCallback(mVgApplication->editEngine(), i)), i);
                }
            }
        }
        // Focused Layer
        else
        {
            lLayer->setHostedVisible(true);
            if (!pFromCloseToStackView)
            {
                lLayer->setLODFactor(mLODsFactors[lLayer->getName()]);
                lLayer->setLoadFactor(mLoadFactors[lLayer->getName()]);
            }
            
            if (!mIsLayerStackDisplayed  || !pFromCloseToStackView)
            {
                if (pIsAnimated)
                {
                    lCallback = registerCallback(VgEngine::VgRefPtr< StopAnimationCallback >(new StopAnimationCallback(lLayer, NULL, NULL)), i);
                }
            }
        }
        
        
        // Get end point position for layer.
        if(pFromCloseToStackView)
        {
            lLayerEndPos = getPositionForLayerInGlobalView(i, mCurrentLayerIndex);
        }
        else
        {
            lLayerEndPos = getPositionForLayerInDetailedView(i, mCurrentLayerIndex);
        }

        if (pIsAnimated)
        {
            float lStartAngle;
            float lEndAngle;
            
            if (pFromCloseToStackView)
            {
                lStartAngle = getParam(eStackNonActiveLayerAngle);
                lEndAngle = (i== mCurrentLayerIndex) ? getParam(eStackActiveLayerAngle) : getParam(eStackNonActiveLayerAngle);
                
                // in the case we are in the same layer, we don't move it.
                if (mCurrentLayerIndex == i && pDirection == eFromGlobalToGlobaView)
                {
                    lStartAngle = lEndAngle = getParam(eStackActiveLayerAngle);
                }
            }
            else
            {
                lStartAngle = (i== mCurrentLayerIndex) ? getParam(eStackActiveLayerAngle) : getParam(eStackNonActiveLayerAngle);
                // on the detailed view the end angle is always 0.0f
                lEndAngle = 0.0f;
            }

            
            animateLayerToPositionAndRotation(lLayer, lLayerStartPos, lLayerEndPos, lCallback, (float)pDuration,lStartAngle,lEndAngle);            
        }
        else
        {
            if (i != mCurrentLayerIndex)
            {
                lLayer->setHostedVisible(false);
                if (!pFromCloseToStackView)
                {
                    lLayer->setVisible(false);
                }
            }
            else
            {
                lLayer->setVisible(true);
                lLayer->setHostedVisible(true);   
            }
            lLayer->setPosition(lLayerEndPos);
        }
    }
}


void VgMyStackedLayerAndCameraHandler::animateLayerToPositionAndRotation(VgEngine::VgRefPtr< VgEngine::VgLayer >const& lLayer, const VgEngine::VgPosition& pStartPos, const VgEngine::VgPosition& pEndPos, VgEngine::VgRefPtr< VgEngine::VgIAnimationCallback >const& pCallback, float pDuration, float pStartAngle, float pEndAngle)
{
    VgEngine::VgRefPtr< VgEngine::VgAnimationDescriptor > lLayerAnimDesc = VgEngine::VgAnimationDescriptor::create();
    lLayerAnimDesc->mDuration = pDuration;
    VgEngine::VgRefPtr< VgEngine::VgVectorInterpolationFunctorDescriptor > lLayerPosDescr (VgEngine::VgVectorInterpolationFunctorDescriptor::create());
    lLayerAnimDesc->mFunctorDescriptors[VgEngine::VgAnimationChannels::mscPositionChannel] = lLayerPosDescr;
    lLayerAnimDesc->mCallback = pCallback;
    lLayerPosDescr->mStartPosition = pStartPos;
    lLayerPosDescr->mEndPosition = pEndPos;
    lLayerPosDescr->mStartTime = 0.0f;
    lLayerPosDescr->mEndTime = pDuration;
    
    
    // we apply the rotation functor if we have some rotation on an
    // active or non-active layer.
    // we don't use the parameter pStartAngle/pEndAngle,
    // because if we are using rotation these may be used with value
    // 0 to put the layer back in its original orientation.
    if (getParam(eStackActiveLayerAngle) != 0.0f || getParam(eStackNonActiveLayerAngle) != 0.0f)
    {
        VgEngine::VgRefPtr< VgEngine::VgAxialRotationQuaternionFunctorDescriptor > lLayerRotationDescr (VgEngine::VgAxialRotationQuaternionFunctorDescriptor::create());
        lLayerAnimDesc->mFunctorDescriptors[VgEngine::VgAnimationChannels::mscOrientationChannel] = lLayerRotationDescr;

        double lCurrentHeadingDegrees = getParam(eStackViewHeading);
        double lHeadingInRad = (lCurrentHeadingDegrees+90.0) * M_PI / 180.0;

        lLayerRotationDescr->mAxis[0] = sin(lHeadingInRad);
        lLayerRotationDescr->mAxis[1] = cos(lHeadingInRad);
        lLayerRotationDescr->mAxis[2] = 0.0f;

        lLayerRotationDescr->mStartAngle = -pStartAngle;
        lLayerRotationDescr->mEndAngle = -pEndAngle;
        lLayerRotationDescr->mCubic = false;
        
        lLayerRotationDescr->mStartTime = 0.0f;
        lLayerRotationDescr->mEndTime = pDuration;
        
    }

    VgEngine::VgRefPtr< VgEngine::VgAnimation > lLayAnim = mVgApplication->editEngine()->editInstanceFactory()->instantiate(lLayerAnimDesc);
    lLayer->setAnimation("",lLayAnim);
    lLayAnim->start();
}

VgEngine::VgIViewPoint& VgMyStackedLayerAndCameraHandler::getStackViewPoint()
{
    mCameraGlobalViewPoint.mPosition = mVgApplication->editEngine()->getPositionToolbox()->offsetPosition(mStackCenter,
                                                                                                          getParam(eStackViewHeading),
                                                                                                          getParam(eStackViewPitch),
                                                                                                          -getParam(eStackViewDistance) );
    
    mCameraGlobalViewPoint.mHeading = getParam(eStackViewHeading);
    mCameraGlobalViewPoint.mPitch  = getParam(eStackViewPitch);
    
    return mCameraGlobalViewPoint;
}


void VgMyStackedLayerAndCameraHandler::animateCameraToViewPoint(const VgEngine::VgIViewPoint& pViewPoint, float pDuration, bool pIsAnimated)
{
    if(pIsAnimated)
    {
        VgEngine::VgIViewPoint lCameraViewpoint = mVgApplication->editEngine()->editCamera()->getViewpoint();
        
        VgEngine::VgRefPtr< VgEngine::VgVectorInterpolationFunctorDescriptor > lPosDescr (VgEngine::VgVectorInterpolationFunctorDescriptor::create());
        lPosDescr->mStartPosition = lCameraViewpoint.mPosition;
        lPosDescr->mEndPosition = pViewPoint.mPosition;
        lPosDescr->mCubic = true;
        
        VgEngine::VgRefPtr< VgEngine::VgAnimation::Descriptor > lAnimDescr = VgEngine::VgAnimation::Descriptor::create();
        lAnimDescr->mDuration = pDuration;
        lAnimDescr->mFunctorDescriptors[VgEngine::VgAnimationChannels::mscPositionChannel] = lPosDescr;
        
        mCameraCallback = new StopAnimationCallback(NULL, mVgApplication->editManipulatorManager(), this);
        lAnimDescr->mCallback = mCameraCallback;
        
        VgEngine::VgRefPtr< VgEngine::VgQuaternionInterpolationFunctorDescriptor > lOrientDesc (VgEngine::VgQuaternionInterpolationFunctorDescriptor:: create());
        lOrientDesc->mCubic = true;
        lOrientDesc->mStartOrientation.mAzimuth = (float)lCameraViewpoint.mHeading;
        lOrientDesc->mStartOrientation.mPitch = (float)lCameraViewpoint.mPitch;
        lOrientDesc->mStartOrientation.mRoll = 0.0f;
        lOrientDesc->mEndOrientation.mAzimuth = (float)pViewPoint.mHeading;
        lOrientDesc->mEndOrientation.mPitch = (float)pViewPoint.mPitch;
        lOrientDesc->mEndOrientation.mRoll = 0.0f;
        lOrientDesc->mStartTime = 0.0f;
        lOrientDesc->mEndTime = pDuration;
        
        lAnimDescr->mFunctorDescriptors[VgEngine::VgAnimationChannels::mscOrientationChannel] = lOrientDesc;
        
        VgEngine::VgRefPtr< VgEngine::VgAnimation > lCamAnim = mVgApplication->editEngine()->editInstanceFactory()->instantiate(lAnimDescr);
        mVgApplication->editEngine()->editAnimationManager()->setCameraAnimation(lCamAnim);
        mVgApplication->editManipulatorManager()->selectManipulator("animation");
        lCamAnim->start();
    }
    else
    {
        if (isGlobalView())
        {
            mVgApplication->editManipulatorManager()->selectManipulator("simpleGesture");
        }
        else
        {
            mVgApplication->editManipulatorManager()->selectManipulator("2D");
            //mVgApplication->editManipulatorManager()->selectManipulator("simpleTrackball");
        }
        mVgApplication->editEngine()->editCamera()->setViewpoint(pViewPoint);
    }
}


VgEngine::VgRefPtr< VgEngine::VgIAnimationCallback > VgMyStackedLayerAndCameraHandler::registerCallback(VgEngine::VgRefPtr< VgEngine::VgIAnimationCallback > pCallback, unsigned int pLayerIndex)
{
    // All VgEngine::VgIAnimationCallback must be freed manually.
    // It frees the previous one before allocating a new one.
    mLayersCallback[pLayerIndex] = pCallback;
    return pCallback;
}


VgEngine::VgPosition* VgMyStackedLayerAndCameraHandler::getCameraPosition()
{
    return &mCamStartViewPoint.mPosition; 
}


void VgMyStackedLayerAndCameraHandler::onLayerSelected()
{
}

void VgMyStackedLayerAndCameraHandler::onSelectorReady()
{
}


unsigned int VgMyStackedLayerAndCameraHandler::getCurrentLayerIndex() const
{
    return mCurrentLayerIndex;
}


void VgMyStackedLayerAndCameraHandler::refreshParameters(unsigned int pWidth, unsigned int pHeight)
{
    
    /*
     * FIELD OF VIEW MANAGEMENT
     * The field of view of the VisioDevKit is adaptative, such that when you change the
     * size of the view, the field of view changes so the object does not appear to change size.
     * in SDK examples before and including 2.0.8409.8434
     * The field of view was set to a "reference screen", thus on very large screens
     * or screens with very high resolution, the map may appear to be very small and 
     * potentially distorted.
     * Using the lNewFieldOfViewBehaviour, we set the horizontal field of view to a fixed
     * value ONCE regardless of the screen size, this makes it predictable what the user
     * will see regardless of their screen resolution.
     * It is important to do it once, because if the screen sizes in portrait and landscape
     * are not exactly the same, slight popping may be visible after the rotation.
     */
    const bool lNewFieldOfViewBehaviour = true;
    static bool once = false;
    if (lNewFieldOfViewBehaviour && !once)
    {
        VgEngine::VgICamera* lCamera = mVgApplication->editEngine()->editCamera();

        double lFovInPortrait = 86.199999; // Field of View for portrait mode
        if (pHeight > pWidth)
        {
            lCamera->setFovX(lFovInPortrait);
        }
        else
        {
            // landscape case
            const double DEG_TO_RAD = .0174532925199432958;
            const double RAD_TO_DEG = 57.2957795130823207758;
            
            double lTanFOVPerPixel = tan(0.5 * lFovInPortrait * DEG_TO_RAD ) / (pHeight);
            
            
            /*
             * recompute the field of view such that in landscape the objects have the same size on the screen, thus when you rotate the screen into landscape you will not have any popping and you will have some extra space on the sides
             */
            double lFovInLandscape = atanf(  ((float)(  lTanFOVPerPixel  * pWidth) ) ) *2.0*RAD_TO_DEG ;
            
            /*
             * Uncommenting the code below will make the horizontal field of view the same
               in both landscape and portrait, thus horizontally, if something touches both borders of the screen, it will touch it in both landscape and portrait.
             */
            // lFovInLandscape = lFovInPortrait
            lCamera->setFovX(lFovInLandscape);
        }
        once = true;
    }
    
    mManipulatorListener->setViewSize(pWidth, pHeight);
    calculateDynamicStackParams();
    refreshStackView();
}

void VgMyStackedLayerAndCameraHandler::refreshStackView()
{
    // As the parameters are to configure the global view, the global view must be refreshed.
    if (isGlobalView())
    {
        VgEngine::VgIViewPoint lViewPoint = getStackViewPoint();
        animateCameraToViewPoint(lViewPoint, 0.0, false);
        
        animateLayersFromCloseToStackView(eFromGlobalToGlobaView, 0.0, false);
    }
}


// FOV refreshers course...
// http://stackoverflow.com/questions/4427662/whats-the-relationship-between-field-of-view-and-lens-length
//
void VgMyStackedLayerAndCameraHandler::calculateDynamicStackParams()
{
    float lDatasetDiameter = (float)getParam(eLayerMaxSize);
     
    double lFovXRadians = mVgApplication->editEngine()->editCamera()->getFovX() * M_PI / 180.0;
    double lTanHalfFovX = tan(lFovXRadians/2.0);
    double lFovYRadians = mVgApplication->editEngine()->editCamera()->getFovY() * M_PI / 180.0;
    double lTanHalfFovY = tan(lFovYRadians/2.0);
    
    // Represents the distance the camera should be away from the scene to fit the layer width.
    double lStackViewDistance = ( (lDatasetDiameter / 2 ) / lTanHalfFovX);
    // A ratio to ensure layer boundaries have some buffer between them and the edge of the view,
    // essentially moves the camera back away from the layers.
    double lStackViewDistanceBufferRatio = 0.8f;
    setParam(eStackViewDistance, (lStackViewDistance * lStackViewDistanceBufferRatio));
    // The vertical height of the camera view
    double lVerticalHeight = ( (lTanHalfFovY * getParam(eStackViewDistance) ) * 2 );
    
    int lNumOfLayers = mVgApplication->editEngine()->editLayerManager()->editLayers().size();
    double lLayerDistanceFromCurrent = lVerticalHeight / (1 + lNumOfLayers);
    setParam(eLayerDistanceFromCurrent, lLayerDistanceFromCurrent);
    
    // Reducing eLayerDistance creates extra buffer space at the bottom and top of the screen,
    // more so with bundles with lots of layers.
    double lLayerDistanceBufferRatio = 0.33f;
    double lLayerDistance = (getParam(eLayerDistanceFromCurrent) * lLayerDistanceBufferRatio);
    setParam(eLayerDistance, lLayerDistance);
}


void VgMyStackedLayerAndCameraHandler::setStackCenterPosition(const VgEngine::VgPosition& pCenterPos)
{
    const VgEngine::VgPositionToolbox* lPosToolbox = mVgApplication->editEngine()->getPositionToolbox();
    mStackCenter = pCenterPos;
    // Convert stack center to have the same spatial reference as the scene
    lPosToolbox->convert(mStackCenter, lPosToolbox->getSceneSRS());
}


const VgEngine::VgPosition& VgMyStackedLayerAndCameraHandler::getStackCenter()
{
    return mStackCenter;
}

void VgMyStackedLayerAndCameraHandler::setParam(const VgMyConfigurableParam pParam, const double pDouble)
{
    if(pParam < eMaxDoubleParams)
    {
        mParam[pParam] = pDouble;
    }
    
    if(pParam == eLayerMaxSize)
    {
        // Dynamically calculate some configurable stack parameters based on the new eLayerMaxSize 
        calculateDynamicStackParams();
    }
}

double VgMyStackedLayerAndCameraHandler::getParam(const VgMyConfigurableParam pParam)
{
    double lRetVal = 0.0;
    if(pParam < eMaxDoubleParams)
    {
        lRetVal = mParam[pParam];
    }
    return lRetVal;
}

./Common/Src/VgMyTextureLoader.cpp

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

#include "VgMyTextureLoader.h"

#include "VgApplication/VgIApplication.h"

#include "VgEngine/VgBinaryBuffer.h"
#include "VgEngine/VgIEngine.h"
#include "VgEngine/VgIResourceManager.h"
#include "VgEngine/VgITextureManager.h"
#include "VgEngine/VgITexture.h"

#include "Modules/3D/VgIconMarkerDescriptor.h"

VgMyTextureLoader::ImageCache::ImageCache()
    : mTriedToLoad(false)
    , mIsSet(false)
{}

VgMyTextureLoader::MarkerCache::MarkerCache ()
    : mTriedToLoad(false)
{}

VgMyTextureLoader::VgMyTextureLoader(VgApplication::VgIApplication* pVgApplication, const std::string& pImageResourceDirectory)
: mVgApplication(pVgApplication)
, mImageResourceDirectory(pImageResourceDirectory)
{}


VgMyTextureLoader::~VgMyTextureLoader()
{
    // delete all texture buffers
    std::hash_map<std::string, MarkerCache>::iterator lMarkerIter;
    for (lMarkerIter = mMarkerCache.begin(); lMarkerIter != mMarkerCache.end(); ++lMarkerIter)
    {
        resetMarker(lMarkerIter);
    }
    
    std::hash_map<std::string, ImageCache>::iterator lImageIter;
    for (lImageIter = mImageCache.begin(); lImageIter != mImageCache.end(); ++lImageIter)
    {
        resetImage(lImageIter);
    }
}


void VgMyTextureLoader::setImage (const std::string& pImageName, const std::string& pFilename)
{
    mImageCache[pImageName].mIsSet = true;
    mImageCache[pImageName].mTexture = NULL;
    mImageCache[pImageName].mTriedToLoad = false;
    mImageCache[pImageName].mFilename = pFilename;
}
  

void VgMyTextureLoader::resetImage(const std::string& pImageName)
{
    std::hash_map< std::string, ImageCache >::iterator lImageIter = mImageCache.find(pImageName);
    if (lImageIter != mImageCache.end())
    {
        resetImage(lImageIter);
    }
}

void VgMyTextureLoader::resetImage(std::hash_map< std::string, ImageCache >::iterator pImageIter)
{
    pImageIter->second.mIsSet = false;
    pImageIter->second.mTexture = NULL;
    pImageIter->second.mTriedToLoad = false;
    pImageIter->second.mFilename.clear();
}


void VgMyTextureLoader::resetMarker(const std::string& pMarkerName)
{
    std::hash_map< std::string, MarkerCache >::iterator lMarkerIter = mMarkerCache.find(pMarkerName);
    if (lMarkerIter != mMarkerCache.end())
    {
        resetMarker(lMarkerIter);
    }
}

void VgMyTextureLoader::resetMarker(std::hash_map< std::string, MarkerCache >::iterator pMarkerIter)
{
    if (pMarkerIter->second.marker.isValid())
    {
        pMarkerIter->second.marker = NULL;
        pMarkerIter->second.mTriedToLoad = false;
    }
}

void VgMyTextureLoader::setMarker (const std::string& pMarkerName, const std::string& pImageName)
{
    resetMarker(pMarkerName);
    mMarkerCache[pMarkerName].imageName = pImageName;
}


VgEngine::VgRefPtr< VgEngine::VgITexture > VgMyTextureLoader::getTextureBuffer (const std::string& pImageName)
{
    std::hash_map< std::string, ImageCache >::iterator lImageIter = mImageCache.find(pImageName);
    if (lImageIter != mImageCache.end())
    {
        if (lImageIter->second.mTriedToLoad == false)
        {
            lImageIter->second.mTriedToLoad = true;
            
            if (lImageIter->second.mIsSet == false)
            {
                return NULL;
            }
        
            VgEngine::VgIEngine* lEngine = (VgEngine::VgIEngine*)mVgApplication->editEngine();
            if ( !lEngine )
            {
                return NULL;
            }
        
            VgEngine::VgITextureManager* lTextureManager = lEngine->editTextureManager();
            if( !lTextureManager )
            {
                return NULL;
            }
            
            VgEngine::VgRefPtr< VgEngine::VgBinaryBuffer > lBuffer;
            // Images should be transparent.
            lBuffer = lEngine->editResourceManager()->readFromFileOrURL(mImageResourceDirectory + lImageIter->second.mFilename);
            lImageIter->second.mTexture = lTextureManager->createTexture(lBuffer);
        }
        return lImageIter->second.mTexture;
    }
    return NULL;
}


VgEngine::VgRefPtr< Vg3DModule::VgIconMarkerDescriptor > VgMyTextureLoader::getMarker(const std::string& pMarkerName)
{
    std::hash_map< std::string, MarkerCache >::iterator lMarkerIter = mMarkerCache.find(pMarkerName);
    if (lMarkerIter != mMarkerCache.end())
    {
        if (lMarkerIter->second.mTriedToLoad == false)
        {
            lMarkerIter->second.mTriedToLoad = true;
            lMarkerIter->second.marker = Vg3DModule::VgIconMarkerDescriptor::create();
            lMarkerIter->second.marker->mScale = 20.f;
            lMarkerIter->second.marker->mIcon = getTextureBuffer(lMarkerIter->second.imageName);
        }
        return lMarkerIter->second.marker;
    }
    return NULL;
}


bool VgMyTextureLoader::isImageSet(const std::string& pImageName) const
{
    
    std::hash_map< std::string, ImageCache >::const_iterator lImageIter = mImageCache.find(pImageName);
    if (lImageIter != mImageCache.end())
    {
        return lImageIter->second.mIsSet;
    }
    return false;
}


bool VgMyTextureLoader::isMarkerSet(const std::string& pMarkerName) const
{
    std::hash_map< std::string, MarkerCache >::const_iterator lMarkerIter = mMarkerCache.find(pMarkerName);
    if (lMarkerIter != mMarkerCache.end())
    {
        return lMarkerIter->second.mTriedToLoad;
    }
    return false;
}

./Common/Inc/Apple/VgMySimulatedLocationProvider.h

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

namespace VgApplication
{
    class VgIApplication;
}

class VgMyLayerAndCameraHandler;
class VgMyLocationListener;

@interface VgMySimulatedLocationProvider : NSObject
{
    NSTimer* mSimulationTimer;
    
    VgApplication::VgIApplication* mVgApplication; 
    VgMyLayerAndCameraHandler* mLayerAndCameraHandler;
    VgMyLocationListener* mListener;
};

-(id) initWithApplication:(VgApplication::VgIApplication*)pVgApplication withLayerAndCameraHandler:(VgMyLayerAndCameraHandler*)pHandler;
-(void) enable;
-(void) disable;
-(bool) isEnabled;
-(void) setListener:(VgMyLocationListener*)pListener;
-(void) fireSimulatedPosition:(NSTimer *)pTimer;

@end

./Common/Inc/Interfaces/VgMyLocationListener.h

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */
#ifndef _VGMYLOCATIONLISTENER_H_
#define _VGMYLOCATIONLISTENER_H_

namespace VgEngine
{
    struct VgPosition;
};

class VgMyLocationListener
{
public:
    
    virtual void updatePosition(const VgEngine::VgPosition& pPosition) = 0;
};

#endif  // _VGMYLOCATIONLISTENER_H_

./Common/Inc/Interfaces/VgMyLocationProvider.h

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */
#ifndef _VGMYLOCATIONPROVIDER_H_
#define _VGMYLOCATIONPROVIDER_H_

namespace VgNavigationModule
{
    class VgINavigationModule;
};

class VgMyLocationListener;

class VgMyLocationProvider
{
public:
    virtual ~VgMyLocationProvider() {}

    virtual void enable() = 0;
    virtual void disable() = 0;
    virtual bool isEnabled() = 0;
    
    virtual void setListener(VgMyLocationListener* pListener) = 0;
};

#endif  // _VGMYLOCATIONPROVIDER_H_

./Common/Src/Apple/VgMySimulatedLocationProvider.mm

/*
 * Copyright 2012, Visioglobe SAS
 * ALL RIGHTS RESERVED
 *
 *
 * LICENSE: Visioglobe grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with Visioglobe SDK; and (3) the
 * names of Visioglobe SAS may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of Visioglobe.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 *
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 *
 * IN NO EVENT WILL VISIOGLOBE BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 *
 * Contact information:  Visioglobe SAS,
 * 300, avenue des papeteries,
 * 38190 Villard-Bonnot
 * FRANCE
 * or:  http://www.visioglobe.com
 */

#import "VgMySimulatedLocationProvider.h"

#include "VgApplication/VgIApplication.h"
#include "VgApplication/VgIModule.h"
#include "VgApplication/VgIModuleManager.h"

#include "VgEngine/VgIEngine.h"
#include "VgEngine/VgICamera.h"
#include "VgEngine/VgPositionToolbox.h"

#include "Modules/Map/VgIMapModule.h"

#include "VgMyLayerAndCameraHandler.h"
#include "VgMyLocationListener.h"


@implementation VgMySimulatedLocationProvider

-(id) initWithApplication:(VgApplication::VgIApplication*)pVgApplication withLayerAndCameraHandler:(VgMyLayerAndCameraHandler*)pHandler
{
    mVgApplication = pVgApplication;
    mLayerAndCameraHandler = pHandler;
    return self;
}

-(void) dealloc
{
    [mSimulationTimer invalidate];
    [super dealloc];
}

-(void) setListener:(VgMyLocationListener*)pListener
{
    mListener = pListener;
}

-(void) enable
{
    // Define the timer interval
    NSTimeInterval lUpdatePositionInterval = 2.0;
    // Start timer
    mSimulationTimer = [NSTimer timerWithTimeInterval:lUpdatePositionInterval target:self selector:@selector(fireSimulatedPosition:) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:mSimulationTimer forMode:NSDefaultRunLoopMode];
}

-(void) disable
{
    [mSimulationTimer invalidate];
    mSimulationTimer = nil;
}

-(bool) isEnabled
{
    bool lIsEnabled = false;
    if(mSimulationTimer != nil)
    {
        lIsEnabled = true;
    }
    return lIsEnabled;
}

-(void)fireSimulatedPosition:(NSTimer *)pTimer
{
    VgEngine::VgICamera* lCamera = mVgApplication->editEngine()->editCamera();
    
    const VgEngine::VgPosition& lCameraPosition = lCamera->getPosition();
    const double lPitch = lCamera->getPitch();
    const double lHeading = lCamera->getHeading();
    
    const double lDistanceToGround = lCameraPosition.mZOrAltitude / fabs(sin(lPitch*M_PI/180.0));
    
    const VgEngine::VgPositionToolbox* lPositionToolbox = mVgApplication->editEngine()->getPositionToolbox();
    
    VgEngine::VgPosition lGroundPositionOnCenterScreen = lPositionToolbox->offsetPosition(lCameraPosition, lHeading, lPitch, lDistanceToGround);
    // lCamera will probably be in a metric SRS.
    // Convert position to Lat/Long to make it easier to debug, the next line is not mandatory.
    lPositionToolbox->convert(lGroundPositionOnCenterScreen, NULL);

    
    const std::string& lLayer = mLayerAndCameraHandler->getFocusedLayerName();
    
    // Computes the floor height of the focused layer
    double lFloorHeight = 0.0;  
    VgMapModule::VgIMapModule* lMapModule = static_cast<VgMapModule::VgIMapModule*>(mVgApplication->editModuleManager()->queryModule("Map"));
    if ( lMapModule )
    {
        float pHeightMax;
        float pHeightMin;
        if ( lMapModule->getHeightRangeForLayer(lLayer, pHeightMax, pHeightMin))
        {
            lFloorHeight = ((pHeightMax + pHeightMin) / 2);
        }
    }
    
    lGroundPositionOnCenterScreen.mZOrAltitude = lFloorHeight;
    
    mListener->updatePosition(lGroundPositionOnCenterScreen);
}

@end
VisioDevKit 2.0, Visioglobe® 2013