Actions
(Difference between revisions)

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

A Relative Map is known as an in-scale map according 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 pixel distance 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 moviments. 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 in the order shown below:

Tip: To make easy the application's screens creation set the first frame as the same shown above (Frame 1) the add the next ones; Thereby you won't need repeating code for the repeated components on the diferents 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 on the frame and the 'area_limit' double. 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' meters distances multiply each one of them for the 'scale' to acquire the horizontal and vertical disntances 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 (beacuse this example is for touch screen mobiles, precisely the Nokia 5800 ExpressMusc) and set fullscreen mode. Create the variables which 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, coding the actions of the buttons, all as shown in the code:

`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) I instanciated a Service object which will be responsible to retrieving the location data in the S60 plattaform, 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 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 -

`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!";	}}`