Wiki

Actions
(Difference between revisions)

Archived:How to implement a Relative Map using GPS in Flash Lite 3.0

Code Example
Compatibility
Platform(s):
Symbian

Article
Created: cristovaodoj (05 Mar 2010)
Last edited: hamishwillee (29 Jun 2012)

21 Mar
2010

A Relative Map is known as an in-scale map with the distance in the real world. For example: You retrieve your current coordinates by GPS and, after that, move 100 meters ahead and then you want to know the distance in pixels on the mobile phone's screen regarding with the scale you chose. Would be better show where you are in the Relative Map in agreement with your movements. Well, I'll explain step-by-step how to do it from implement the geometric functions to calculate the relation between the real world distance and the relative distance to retrieve asynchronously GPS location informations.

Contents

Frames Design

1.1 - For starts you must create a new mobile project and select Flash Lite 3.0 and ActionScript 2.0 as player version and ActionScript version, respectively.

1.2 - Insert 4 (four) KeyFrames as shown below:

Tip: To make easy the application's screens creation set the first frame as the same shown above (Frame 1) then add the next ones; Thereby you won't need repeat code for the repeated components on the different frames which have the same functionalities.

Relative Map Scheme

Let's understand what 'area_limit' is; It is the maximum value in meters which you can move vertically or horizontally. As the name says 'scale' represents the scale between the drawn rectangle height in the frame and the 'area_limit' double value. This value means that every walked meter M in the real world there are P 'walked' pixels on the mobile screen. So, we had found the 'd_x' and 'd_y' distances in meters, multiply each one of them for the 'scale' to acquire the horizontal and vertical distances in pixels. For more details see the scheme shown below:

Code Explanation

Here I'll discourse a little about each frame code used to implement the Relative Map.

3.1 - We must disable the keypad (because this example is for touch screen mobiles, precisely the Nokia 5800 XpressMusic) and set full-screen mode. Create the variables that represent the central point latitude and longitude and the map area limit. The limit can be whatever numeric value you want; if you want to change it the only thing you have to do is modify the ComboBox labels. Finally, code the actions of the buttons, all like is shown:

`fscommand2("DisableKeypadCompatibilityMode"); // Disable keypadfscommand2("Fullscreen", true); // Set FullScreen modefscommand2("SetQuality", "high"); // Set high quality var UPPER_X_RELATIVE_MAP:Number = 10;var UPPER_Y_RELATIVE_MAP:Number = 130;var HEIGHT_RELATIVE_MAP:Number = 340;var WIDTH_RELATIVE_MAP:Number = 340;var ICON_HEIGHT:Number = 6;var ICON_WIDTH:Number = 6; var longitude_center:Number = new Number();var latitude_center:Number = new Number();var area_limits:Number = new Number(); get_center_location_btn.onRelease = function() {	area_limits = int(area_limit.text.split(" ")[0]);	gotoAndStop(2);}; exit_btn.onRelease = function() {	fscommand2("Quit");}; stop();`

3.2 - In the frame 2 (two) a Service object is instantiated which will be responsible to retrieving the location data in the S60 platform, however first it makes necessary import the library 'com.nokia.lib.Service'. Now code the 'cancel_gps' button to cancel the access to the gps when you click it.

Tip: For better screen control flow use the asynchronous GetLocation function.
`import com.nokia.lib.Service; var location = new Service("Service.Location", "ILocation");var inParams = {LocationInformationClass:"GenericLocationInfo"}; location.GetLocation(inParams,onReceive); function onReceive(transactionID:Number, eventID:String, outParam:Object) {	if (outParam.ErrorCode == 0) {		var outList = outParam.ReturnValue;		longitude_center = outList.Longitude;// Contains longitudinal data		latitude_center = outList.Latitude;// Contains latitudinal data		gotoAndStop(4);	} else {		var errorId = outParam.ErrorCode;		gotoAndStop(3);	}} cancel_gps.onRelease = function() {	var inParamsCancel = {CancelRequestType:"GetLocCancel"};	var outParamsCancel = location.CancelNotification(inParamsCancel);	var errorIdCancel = outParamsCancel.ErrorCode;	gotoAndStop(1);};`

3.3 - In the third frame we have the screen shown when any retrieving GPS location error occurs.

Note: The dark screen (frame 3) is a button with instance name 'screen_unlocker_btn'. When occurs an errror just tap the screen to return to the main screen (frame 1).
`screen_unlocker_btn.onRelease = function() {	gotoAndStop(1);};`

3.4 - To conclude we need user the 'Trace' function to retrieving the GPS location repeatedly on a pre-defined time, below in the code it was assigned the value 1000000 which is equivalent to 1 second. every callback function onNotify execution we will set the MovieClip 'me_icon_mc' position which represents your current position in the Relative Map and to the Dynamic Text field 'distance_from_start' we assign the distance between you and the central point. Important, if you get out of the map bounds your icon will be on the edge and a message will be shown in the 'alert' field.

`import com.nokia.lib.Service; var location = new Service("Service.Location", "ILocation");var updateOptions = {UpdateInterval:1000000};var inParamsTrace = {LocationInformationClass:"GenericLocationInfo", Updateoptions:updateOptions}; location.Trace(inParamsTrace,onNotify); function onNotify(transactionID:Number, eventID:String, outParam:Object) {	if (outParam.ErrorCode == 0) {		var outList = outParam.ReturnValue;		longitude = outList.Longitude;// Contains longitudinal data		latitude = outList.Latitude;// Contains latitudinal data 		setMeIconPosition(latitude,longitude); 		// Calculates the distance between center and the treasure		var sourceDistance = {Longitude:longitude, Latitude:latitude, Altitude:0.0};		var destinationDistance = {Longitude:longitude_center, Latitude:latitude_center, Altitude:0.0};		var inParamsDistance = {MathRequest:"FindDistance", DistanceParamSource:sourceDistance, DistanceParamDestination:destinationDistance};		var outParamsDistance = location.Calculate(inParamsDistance); 		if (outParamsDistance.ErrorCode == 0) {			var distance = outParamsDistance.ReturnValue;			var distStr = distance.toString()+"00";			distance_from_start.text = distStr.split(".")[0]+"."+substring(distStr.split(".")[1], 0, 2);		} else {			var errorId = outParamsDistance.ErrorCode;		} 	} else {		var errorId = outParam.ErrorCode;	}} function setMeIconPosition(latitude:Number, longitude:Number):Void { 	var d_y = location.Calculate({MathRequest:"FindDistance", DistanceParamSource:{Longitude:longitude_center, Latitude:latitude_center, Altitude:0.0}, DistanceParamDestination:{Longitude:longitude_center, Latitude:latitude, Altitude:0.0}}).ReturnValue;	var d_x = location.Calculate({MathRequest:"FindDistance", DistanceParamSource:{Longitude:longitude_center, Latitude:latitude_center, Altitude:0.0}, DistanceParamDestination:{Longitude:longitude, Latitude:latitude_center, Altitude:0.0}}).ReturnValue;	var scale = HEIGHT_RELATIVE_MAP/(2*area_limits);// or WIDTH 	if (latitude_center<latitude) {		if (d_y>area_limits) {			vertical_value = UPPER_Y_RELATIVE_MAP-(ICON_HEIGHT/2);		} else {			vertical_value = UPPER_Y_RELATIVE_MAP+(HEIGHT_RELATIVE_MAP/2)-(scale*d_y)-(ICON_HEIGHT/2);		}	} else {		if (d_y>area_limits) {			vertical_value = UPPER_Y_RELATIVE_MAP+HEIGHT_RELATIVE_MAP-(ICON_HEIGHT/2);		} else {			vertical_value = UPPER_Y_RELATIVE_MAP+(HEIGHT_RELATIVE_MAP/2)+(scale*d_y)-(ICON_HEIGHT/2);		}	} 	if (longitude_center<longitude) {		if (d_x>area_limits) {			horizontal_value = UPPER_X_RELATIVE_MAP+WIDTH_RELATIVE_MAP-(ICON_WIDTH/2);		} else {			horizontal_value = UPPER_X_RELATIVE_MAP+(WIDTH_RELATIVE_MAP/2)+(scale*d_x)-(ICON_WIDTH/2);		}	} else {		if (d_x>area_limits) {			horizontal_value = UPPER_X_RELATIVE_MAP-(ICON_WIDTH/2);		} else {			horizontal_value = UPPER_X_RELATIVE_MAP+(WIDTH_RELATIVE_MAP/2)-(scale*d_x)-(ICON_WIDTH/2);		}	} 	me_icon_mc._y = vertical_value;	me_icon_mc._x = horizontal_value; 	if (d_y>area_limits || d_x>area_limits) {		out_of_bounds = true;		alert.text = "Out of bounds!";	}}`