mapnavproviderrefapp/src/mnrpengine.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:31:27 +0100
branchRCL_3
changeset 18 870918037e16
parent 0 522cd55cc3d7
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201033 Kit: 201035

/*
* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). 
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:  CMnrpEngine class implementation
*
*/


#include <coemain.h>
#include <aknlists.h>
#include <barsread2.h>
#include <barsc2.h> 

#include <lbsposition.h>
#include <lbspositioninfo.h>

#include <EPos_CPosLandmark.h>
#include <EPos_CPosLandmarkDatabase.h>

#include <mnrefproviderengine.rsg>

#include "../inc/debug.h"
#include "mnrpengine.h"

_LIT( KCitiesResourceFile, "\\resource\\mnrefproviderengine.rsc");

// ============================ MEMBER FUNCTIONS ===============================

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
CMnrpEngine::CMnrpEngine()
    { 
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
EXPORT_C CMnrpEngine::~CMnrpEngine()
    {
    iPlaces.ResetAndDestroy();
    iFileSession.Close();
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
EXPORT_C CMnrpEngine* CMnrpEngine::NewL()
    {
    CMnrpEngine* self = new (ELeave) CMnrpEngine();
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );
    return self;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CMnrpEngine::ConstructL()
    {
    User::LeaveIfError( iFileSession.Connect() );
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
EXPORT_C TArray<CPosLandmark*> CMnrpEngine::KnownPlacesL()
    {
    if ( iPlaces.Count() == 0 )
        {
        TRAP_IGNORE( LoadKnownPlacesL() );
        }

    return iPlaces.Array();        
    }
    
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
EXPORT_C CPosLandmark* CMnrpEngine::AddressToCoordLC( const CPosLandmark& aAddress )
    {
    CPosLandmark* lm = AddressToCoordL( aAddress );
    if ( lm )
        {
        CleanupStack::PushL( lm );
        return lm;
        }
    else
        {
        User::Leave( KErrNotFound );
        return NULL;
        }
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
EXPORT_C CPosLandmark* CMnrpEngine::AddressToCoordL( const CPosLandmark& aAddress )
    {
    TPtrC city, country;
    aAddress.GetPositionField( EPositionFieldCity, city );
    
    TArray<CPosLandmark*> pois = KnownPlacesL();
    
    if ( city.Length() )
        {
        for ( TInt i = 0; i < pois.Count(); i++ )
            {
            TPtrC poiCity;
            pois[i]->GetPositionField( EPositionFieldCity, poiCity );
            if ( poiCity.CompareF( city ) == 0 )
                {
                return CPosLandmark::NewL( *pois[i] );
                }
            }
        }
    
    return NULL;
    }
    
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
EXPORT_C CPosLandmark* CMnrpEngine::AddressToCoordLC( const TDesC& aAddress )
    {
    CPosLandmark* lm = AddressToCoordL( aAddress );
    if ( lm )
        {
        CleanupStack::PushL( lm );
        return lm;
        }
    else
        {
        User::Leave( KErrNotFound );
        return NULL;
        }
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
EXPORT_C CPosLandmark* CMnrpEngine::AddressToCoordL( const TDesC& aAddress )
    {
    TArray<CPosLandmark*> pois = KnownPlacesL();

    if ( aAddress.Length() )
        {
        for ( TInt i = 0; i < pois.Count(); i++ )
            {
            TPtrC city, country;
            pois[i]->GetPositionField( EPositionFieldCity, city );
            pois[i]->GetPositionField( EPositionFieldCountry, country );
            
            if ( aAddress.FindF( city ) >= 0 )
                {
                return CPosLandmark::NewL( *pois[i] );
                }
            }
        }
        
    return NULL;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
EXPORT_C TReal32 CMnrpEngine::DistanceBetweenLandmarks( 
    const CPosLandmark& aFrom,
    const CPosLandmark& aTo )
    {
    TRealX nan;
    nan.SetNaN();
    TReal32 distance = nan;
    
    TLocality locFrom, locTo;

    if ( aFrom.GetPosition( locFrom ) == KErrNone &&
         aTo.GetPosition( locTo ) == KErrNone )
        {
        TReal32 dist;
        if ( locFrom.Distance( locTo, dist ) == KErrNone )
            {
            distance = dist;
            }
        }
    return distance;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
EXPORT_C void CMnrpEngine::FindClosestPoisL( 
    const CPosLandmark& aReference,
    RArray<CMnrpEngine::TDistanceToPoi>& aNeighbourPois,
    TInt aMaxMatches )
    {
    aNeighbourPois.Reset();
    TArray<CPosLandmark*> pois = KnownPlacesL();

    // calc distances to known places and find out closest ones
    for ( TInt i = 0; i < pois.Count(); i++ )
        {
        CPosLandmark* poi = pois[i];

        TReal32 distance = DistanceBetweenLandmarks( aReference, *poi );
        
        if ( Math::IsNaN( distance ) )
            {
            continue;
            }
        
        TDistanceToPoi newDistToPoi;
        newDistToPoi.iPoiIndex = i;
        newDistToPoi.iDistance = distance;

        for ( TInt k = 0; k < aNeighbourPois.Count(); k++ )
            {
            TDistanceToPoi distToPoi = aNeighbourPois[k];
            if ( distance < distToPoi.iDistance )
                {
                // current POI is closer to reference than current neighbour
                aNeighbourPois.InsertL( newDistToPoi, k );
                break;
                }
            }

        if ( aNeighbourPois.Count() < aMaxMatches )
            {
            aNeighbourPois.AppendL( newDistToPoi );
            }

        if ( aNeighbourPois.Count() > aMaxMatches )
            {
            aNeighbourPois.Remove( aNeighbourPois.Count() - 1 ); // remove last
            }
        }
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
CPosLandmark* CMnrpEngine::CreateCloseLandmarkLC( 
    const CPosLandmark& aReference,
    TReal32 aDistance )
    {
    CPosLandmark* lm = CPosLandmark::NewLC( aReference );
    TPtrC oldName;
    lm->GetLandmarkName( oldName );
    
    // create street in the form of "50 km to <POI name>"
    const TInt KDistValueLen = 5; // "40000"
    const TInt KAdditionalChars = 7; // " km to "

    _LIT( KLocationNameFormat, "%d m to %S" );
    _LIT( KLocationNameFormatKm, "%d km to %S" );

    HBufC* locName = HBufC::NewLC( oldName.Length() + KDistValueLen + KAdditionalChars );

    if ( aDistance < 1000 )
        {
        locName->Des().Format( KLocationNameFormat, TInt( aDistance ), &oldName );
        }
    else
        {
        locName->Des().Format( KLocationNameFormatKm, TInt( aDistance / 1000 ), &oldName );
        }

    lm->SetPositionFieldL( EPositionFieldLocationName, *locName );
    lm->SetPositionFieldL( EPositionFieldStreet, *locName );
   
    CleanupStack::PopAndDestroy( locName );
    return lm; // left in stack
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
EXPORT_C CPosLandmark* CMnrpEngine::CoordToAddressLC( const TCoordinate& aLocation )
    {
    TArray<CPosLandmark*> pois = KnownPlacesL();

    // find closest POI
    RArray<TDistanceToPoi> matches;
	CleanupClosePushL( matches );
    
    CPosLandmark* temp = CPosLandmark::NewLC();
    TLocality loc( aLocation, 0 ); // accuracy is not used by this implementation
    temp->SetPositionL( loc );
    FindClosestPoisL( *temp, matches, 1 ); // only one match needed
    CleanupStack::PopAndDestroy( temp );
    
    if ( matches.Count() < 1 )
		{
		User::Leave( KErrNotFound );
		}

    TDistanceToPoi distToPoi = matches[0];
	CleanupStack::PopAndDestroy( &matches );

    CPosLandmark* lm = CreateCloseLandmarkLC(
        *pois[distToPoi.iPoiIndex],
        distToPoi.iDistance );

    return lm; // left in stack
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
EXPORT_C void CMnrpEngine::BestCoordToAddressMatchesL( 
    const TCoordinate& aLocation,
    RPointerArray<CPosLandmark>& aMatches,
    TInt aMaxMatches )
    {
    TArray<CPosLandmark*> pois = KnownPlacesL();

    // find closest POIs
    RArray<TDistanceToPoi> matches;
    CleanupClosePushL( matches );
    
    CPosLandmark* temp = CPosLandmark::NewLC();
    TLocality loc( aLocation, 0 ); // accuracy is not used by this implementation
    temp->SetPositionL( loc );
    FindClosestPoisL( *temp, matches, aMaxMatches );
    CleanupStack::PopAndDestroy( temp );
    
    for ( TInt i = 0; i < matches.Count(); i++ )
        {
        TDistanceToPoi distToPoi = matches[i];
        
        CPosLandmark* lm = CreateCloseLandmarkLC( 
            *pois[distToPoi.iPoiIndex], 
            distToPoi.iDistance );
            
        aMatches.AppendL( lm );    
        CleanupStack::Pop( lm );
        }
    CleanupStack::PopAndDestroy( &matches );
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
EXPORT_C void CMnrpEngine::FindResourceFileL( 
    const TDesC& aFilePathAndName,
    TFileName& aRscFile )
    {
    TParse parse;
    parse.Set( aFilePathAndName, NULL, NULL );
    
    TFindFile finder( iFileSession );
    if ( finder.FindByDir( parse.NameAndExt(), parse.Path() ) == KErrNone )
        {
        aRscFile.Copy( finder.File() );
        }
    else
        {
        User::Leave( KErrNotFound );
        }
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
EXPORT_C RFs& CMnrpEngine::Fs() 
    { 
    return iFileSession;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CMnrpEngine::LoadKnownPlacesL()
    {
    TFileName resourceFile;
    FindResourceFileL( KCitiesResourceFile(), resourceFile );

    CResourceFile* resFile = CResourceFile::NewLC( iFileSession, resourceFile, 0, 0 );
    resFile->ConfirmSignatureL( 0 );

    RResourceReader reader;

    reader.OpenLC( resFile, R_MNREFPROVIDERENGINE_PLACES );
    ReadPlacesResourceL( reader );
    CleanupStack::PopAndDestroy( &reader );
    
    CleanupStack::PopAndDestroy( resFile );
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CMnrpEngine::ReadPlacesResourceL( RResourceReader& aReader )
    {
    TInt size = aReader.ReadInt16L();

    for ( TInt i = 0; i < size; i++ )
        {
        HBufC* city = aReader.ReadHBufCL();
        CleanupStack::PushL( city );
        HBufC* country = aReader.ReadHBufCL();
        CleanupStack::PushL( country );

        TReal64 lat = aReader.ReadReal64L();
        TReal64 lon = aReader.ReadReal64L();
        
        CPosLandmark* lm = CPosLandmark::NewLC();
        lm->SetLandmarkNameL( *city );
        
        lm->SetPositionFieldL( EPositionFieldCity, *city );
        lm->SetPositionFieldL( EPositionFieldCountry, *country );
        
        TLocality coord;
        coord.SetCoordinate( lat, lon );
        lm->SetPositionL( coord );
        
        iPlaces.AppendL( lm );
        CleanupStack::Pop( lm );
        CleanupStack::PopAndDestroy( country );
        CleanupStack::PopAndDestroy( city );
        }
    }