Using Map Image API
This API relies on functionality provided by external applications, Provider
Applications, which are executed in a separate process from client. Rendering
services are accessed through the
CMnMapImage class. Client
creates it using the NewL method. The provider application
is always executed in standalone mode.
Some methods of
CMnMapImage are asynchronous (see CMnMapImage::RenderL),
and they must be completed or cancelled before any other asynchronous requests
are made. If an asynchronous method can leave, and it leaves, then no asynchronous
request is outstanding.
The connection to the provider application is closed when this class is
destroyed, but it does not necessarily mean that the provider application
is closed too. This depends on user actions and/or provider application behavior.
Map image parameters
Map image parameters determine behavior of all use cases of this API: image
rendering, as well as coordinate conversions. The parameters are collected
within the
TMnMapImageParams class and described below.
| Center Point |
The world coordinate in WGS-84, which should be positioned in the center
of the rendered map image. |
|
Size
|
Width and height of needed image in pixels.
|
|
Area
|
Width and height of the visible world area in meters. See more info
below.
|
|
Direction
|
"Heading" of the image. See more info below.
|
|
Image Type
|
Type of the image: scalable vector map or satellite images.
|
Direction
Map image is by default directed to North (except if center point is at
North Pole) but client can specify any other direction via
TMnMapImageParams::SetDirection().
Image direction is defined as clockwise angle between two vectors:
-
vector from center point towards North Pole parallel to center’s longitude.
If center is positioned at North Pole, then this vector is directed towards
South Pole parallel to center’s longitude.
-
vector from center point towards center of image’s top side (vertical
axis of the image).
This direction parameter can be thought of as "true heading" of the image.
Area
Area parameter describes the size of world area visible in the map image.
It is defined via two arguments: width and height. Height is the length in
meters of the line, parallel to the image direction and going through the
center point. Width is the length of the line, orthogonal to the image direction
and going through center point. These two parameters define an ellipse, covering
the world area, which is required to be visible on the map.
Note, that the actual visible area may be larger than that specified by
width and height, if the given image size and visible area have different
aspect ratios. The actual aspect ratio of the map is determined by the projection
algorithms used by the provider application.
The picture below describes the definition of center point, direction and
area parameters. "Latitude" and "Longitude" are respectively center point's
meridian and parallel.
Scale
There is no globe to plane projection that could preserve distances between
any two points in the whole map extent. Therefore, the scale of a map cannot
be constant on the whole map and will vary from place to place. (Printed maps
almost always have a scale indicator, but it is only a so called principal
scale, or "nominal" scale, which is the ratio of the Earth scale to the radius
of the sphere, used for map generation. This scale matches the actual map
image scale only at some points or lines.)
Therefore, it is not possible to reliably measure real world distances
based on distance on map image. Instead, use the
TCoordinate::Distance() method
to calculate distances between world coordinates and CMnMapImage::GetWorldCoordinate() to
find world coordinates corresponding to a given image point.
Related APIs
CMnMapImage::GetWorldCoordinate()TCoordinate::Distance()TMnMapImageParamsTMnMapImageParams::SetDirection()
Obtaining bitmap of specified world area
The client application uses
CMnMapImage to specify various
parameters of map image it wants to receive and to issue rendering request.
Rendering request is asynchronous and the client handles it itself or registers
a listener, which will be informed about request completion. The listener
must be derived from MMnMapImageRenderCallback.
The main steps of that use case are:
-
Find Provider Application, which supports Map Image service, by using
MnProviderFinder::FindProvidersL() from
Map and Navigation Provider Discovery API.
-
Create the
CMnMapImage class with instance of CMnProvider,
selected on step 1.
-
Define map image parameters in
CMnMapImage::MapImageParams().
It is recommended to explicitly define all the parameters without relying
on default values.
-
Optionally, set options, which are desired to be shown on map via
SetShowOptions.
-
Create a new instance of
CFbsBitmap, size in pixels,
sufficient to fit the image of size defined in TMnMapImageParams::SetSize() (taken CMnMapImage::SetTargetOrigin() into account as well). Or, reuse another instance, which meets these requirements.
-
Issue rendering request by one of
RenderL overloads with
parameter selected on Step 5.
-
When the asynchronous request is successfully completed, the resulting
image is contained in the bitmap provided on Step 6.
This sequence (with slight changes) is described on the diagram below.
Note the
callback object, it is one of client's classes,
which implements the MMnMapImageRenderCallback interface.
This object is notified when the rendering process is finished. This API uses
an active object internally to realize that feature, and hence that callback
is called only when client's thread is idle (i.e. its Active Scheduler is
processing its active objects).
Alternatively, the client can define its own active object and use its
iStatus member
variable as parameter to the CMnMapImage::RenderL method.
The following example shows how to code the sequence described below. For
simplicity, asynchronous rendering request is handled synchronously, though
it is not recommended in real applications: either a callback class should
be used, or client's own active object.
#include <fbs.h>
#include <gdi.h>
#include <mnmapimage.h>
CFbsBitmap* GetBitmapLC(
TCoordinate& aCenter,
TSize& aSize,
TReal32 aVisibleArea, // in meters
CMnProvider& aProvider )
{
// Create target bitmap
CFbsBitmap* bitmap = new (ELeave) CFbsBitmap;
CleanupStack::PushL( bitmap );
User::LeaveIfError( bitmap->Create( aSize, EColor16M ) );
// Create renderer
CMnMapImage* image = CMnMapImage::NewL( aProvider );
CleanupStack::PushL( image );
// Define map image parameters
TMnMapImageParams params;
params.SetCenterPoint( aCenter );
params.SetSize( aSize );
params.SetVisibleArea( aVisibleArea, aVisibleArea );
params.SetDirection( 0 ); // directly towards North
params.SetImageType( TMnMapImageParams::ETypeSatelliteImage );
image->SetMapImageParams( params );
// Optional settings
image->SetShowOptions(
CMnMapImage::EShowOptionPois | CMnMapImage::EShowOptionText );
// Now render!
TRequestStatus status;
image->RenderL( *bitmap, status );
User::WaitForRequest( status );
User::LeaveIfError( status.Int() );
// Cleanup and return
CleanupStack::PopAndDestroy( image );
return bitmap; // left in cleanup stack
}
Related APIs
CFbsBitmapCMnMapImageCMnMapImage::MapImageParams()CMnMapImage::RenderLCMnMapImage::SetTargetOrigin()CMnProviderMMnMapImageRenderCallbackMnProviderFinder::FindProvidersL()RenderLSetShowOptionsTMnMapImageParams::SetSize()callbackiStatus
Converting between image and world coordinates
The actual rendering engine of the provider application can utilize any
projection algorithms, which affect how world locations and areas are represented
by the map image. Also, as said before, the client cannot calculate distances
in the world, based on distances in the map image. To resolve such problems
there is a coordinate conversion functionality, which converts world coordinates
to map image offsets and vice versa.
In case the client application needs to draw something on top of map image,
it must know how world coordinates are mapped to pixels of image.
CMnMapImage provides
the GetImageCoordinate() method to achieve that. It accepts
world coordinate in WGS-84 as parameter an returns offset in pixels from the
top left corner of the map image. (Note that this is not the top left
corner of the bitmap image if CMnMapImage::TargetOrigin() is
not TPoint(0,0). )
The given coordinate may even be outside of the area drawn on the map image,
in which case negative values in the result value will denote a point to the
left of the left border and/or above the top border of the image, and values
bigger than width or height denote a point to the right of the right image
border or below its bottom border. This can be used to estimate the relative
position of a location, which is not visible on the map image. However, such
estimation is not always possible, especially if that location is much far
away from the image area borders. This function returns
KErrUnknown in
such cases.
If the client wants to identify a real world location, which corresponds
to a given pixel in the map image, it can do so by calling
CMnMapImage::GetWorldCoordinate().
The output is a WGS-84 coordinate. In this case it is required that the input
image coordinate fits to the image borders, otherwise KErrArgument is
returned.
It is also possible that a given image coordinate has no corresponding
coordinate, as in the case when a semisphere of the globe is drawn and image
corners contain no map data. In that case
KErrUnknown is
returned.
These methods are not asynchronous as they do not require IPC communication
with server side of the provider application and are expected to be fast enough
so that the client can call them quite often without big performance penalty.
In practice, the client application uses these two methods after an image
has been rendered. Therefore, instead of a sequence diagram, only a code example
is given for this use case.
void FindRealDiagonalLengthL(
const CMnMapImage& image, TReal32 aDiagonal )
{
// Find coordinate of left top corner
TCoordinate leftTop;
User::LeaveIfError(
image.GetWorldCoordinate( TPoint( 0, 0 ), leftTop ) );
// Find coordinate of right bottom corner
TCoordinate rightBottom;
User::LeaveIfError(
image.GetWorldCoordinate(
image.MapImageParameters().Size().AsPoint(),
rightBottom ) );
// Calculate distance
TReal32 distance;
User::LeaveIfError( rightBottom.Distance( leftTop, distance ) );
aDiagonal = distance;
}
The usage of
CMnMapImage::GetImageCoordinate() is very
similar and is not shown here.
Related APIs
CMnMapImageCMnMapImage::GetImageCoordinate()CMnMapImage::GetWorldCoordinate()CMnMapImage::TargetOrigin()GetImageCoordinate()KErrArgumentKErrUnknownTPoint(0,0)
Security
This API itself does not require any capabilities from the client (except
for the
Location capability, when the current location option
is required to be drawn, see CMnMapImage::SetShowOptions()).
However, the client must be aware that, as was mentioned above, the API
utilizes provider applications for serving clients' requests. Provider applications
run in their own process and might require some capabilities. For example,
a provider application, which needs to access network in order to retrieve
map content, might require
NetworkServices capability. If
the client does not have it, then the provider application refuses serving
the client's request (or select a workaround, e.g. remain in offline mode).
If the service is refused due to lack of capabilities, the error code is KErrPermissionDenied.
Related APIs
CMnMapImage::SetShowOptions()KErrPermissionDeniedLocationNetworkServices
Error handling
This API uses only standard error and leave codes. Panic codes are defined
in the
mnerrors.h header file.
|
|
|
KMnPanicDuplicateRequest
|
Raised if the client issues a new asynchronous request before the previous
one is completed or cancelled. For this API it happens if the client calls
CMnMapImage::RenderL before
the previous request is completed or cancelled.
|
Related APIs
CMnMapImage::RenderLKMnPanicDuplicateRequest
Memory overhead
The biggest memory consumption, which can be caused by using this API is
determined by two factors:
-
Rendering is implemented by the provider application, which is loaded,
when the
CMnMapImage class is created and remains in memory
until it is destroyed. However, in client's heap only a small amount of memory
is allocated, to maintain the session with the renderer, while most of the
memory is allocated by the renderer itself from global memory.
-
Bitmap size. Again, the main amount of memory is allocated in the heap
of Font and Bitmap Server and not in the client's heap.
Despite the fact that largest portions of memory are allocated not in
client's heap, the client still has to take responsibility of memory usage.
The following practices can help overall system performance a lot:
-
Destroy CMnMapImage instances, when not needed. This will allow the provider
application to exit and free some memory for other applications. Note: starting
the provider application may take some time, so it is still not recommended
to construct and destroy this class too frequently.
-
Do not keep too many bitmap objects allocated. Usually, the application
needs only two: one for rendering purposes and another one for drawing on
the screen, whenever
CCoeControl::Draw() is called.
Related APIs
CCoeControl::Draw()CMnMapImage
Extensions to the API
This API does not allow extending.
See also
See also related APIs:
Related APIs
CMnMapImageCMnMapImage::RenderLNewL