Other Wrong decimal format for Location object?

udg

Expert
Licensed User
Longtime User
Hi all,

when using the following code to store last lat/lon in a map and then to a file, the resulting string uses a comma on the seconds part due to my locale settings
B4X:
MParameters.Put("lastloclat",LastLoc.ConvertToSeconds(LastLoc.Latitude))
so when I read it back (from file) I have to replace commas with dots in order to avoid an illegal value error whe initializing a Location object with those coordinates.

Is there a way to force ConvertToSeconds to use a decimal point instead of a comma before writing? A JavaObject or Reflection solution will be preferable to the use of an extra lib (just a matter of personal taste).

TIA

udg
 

JordiCP

Expert
Licensed User
Longtime User
You can change it before saving
B4X:
MParameters.Put("lastloclat",LastLoc.ConvertToSeconds(LastLoc.Latitude).Replace(",","."))
 
Upvote 0

udg

Expert
Licensed User
Longtime User
@JordiCP : You're right, but the spirit of my message was more "could it be considererd a bug" rather than "help me to find a way".
Strictly speaking it is not a bug since ConvertToSecond should produce a string from a double and as any other numeric conversion it should take in consideration locale settings. But, this could also seen as a special case where there's no reason to produce a comma since that function is used only in the context of a lat/lon conversion and the format expected calls for a decimal point.

As said, I can see reasons why it works as it does.

@LucaMs : using Replace (before writing or after reading it's the same for the way I use it in my app) is the simplest solution for the problem at hand. I used the multiply/divide by 100 for currency values in order to avoid rounding errors but here it will lead to too much work... (yes, two operations instead of one is too much eheheh).

Thanks all
 
Upvote 0

udg

Expert
Licensed User
Longtime User
Oooh, I see your point.
No problem, since it is a private, family app. All our devices will return a comma and so the conversion will be always successful.
For a general solution we should operate as we do for Date/Time format: save current one, modify to suits our needs and finally restore the original one.
 
Upvote 0

JordiCP

Expert
Licensed User
Longtime User
But, this could also seen as a special case where there's no reason to produce a comma since that function is used only in the context of a lat/lon conversion and the format expected calls for a decimal point.
Uhmm. Not sure to understand. What do you mean by "the format expected calls for a decimal point"? Where?
 
Upvote 0

udg

Expert
Licensed User
Longtime User
Location.Initialize2(Lat as string, Lon as string)
where Lat/Lon (if using seconds) should be formatted as
[+-]DD:MM:SS.SSSSS

My comment is about a possible internal convertion made by the Location object itself. It could read in any decimal separator and "convert" it to the decimal point it expects. Same for the "output" functions like ConvertToSeconds; why not just produce a string using the decimal point ? Are there uses where somebody needs to read it with a comma as the decimal separator?
Maybe a formal definition will call for different separators depending on the country where the coordinate system is used, but eventually an international standard could set it to a single type, valid everywhere.

Anyway, the whole discussion find its roots in what I found coding my app:
1. blindingly saving a string produced by ConvertToSeconds (not considering it would have been outputted with a comma as its decimal separator)
2. blindingly using that string to initialize a Location object (which expected a decimal point separator)
3. Error arose.

I quickly figured out the problem and fixed it, but found useful to post my message for two reasons:
- help others to avoid the same pitfall
- see if could be raesonable to revise Location object's functions to standardize on the decimal point separator

udg
 
Upvote 0

JordiCP

Expert
Licensed User
Longtime User
Location.Initialize2(Lat as string, Lon as string)
where Lat/Lon (if using seconds) should be formatted as
[+-]DD:MM:SS.SSSSS
You are right, now I see it!
It is strange, because Android documentation describes it as
B4X:
  FORMAT_SECONDS
Constant used to specify formatting of a latitude or longitude in the form "DDD:MM:SS.SSSSS" where D indicates degrees, M indicates minutes of arc, and S indicates seconds of arc (1 minute = 1/60th of a degree, 1 second = 1/3600th of a degree).
I made a small test program because I wanted to see how the original Android Location object behaved, in comparison with the BA object.

In both cases (BA and Java) conversion to seconds is made using local settings, so we can conclude that the android documentation is at least confusing

The "problem" is with the BA initialize2 method, as there isn't any equivalent in Java. As you said it expects only the exact syntax no taking into account locale settings.

Not necessarily a bug, but agree that it is incoherent that we can not initialize a new Location object with the same format that the methods from that object give.
Surely it would be problematic changing it, but perhaps adding a "initialize3" method which takes into account locale settings (as the convertToSeconds does) and update documentation would be the correct.

B4X:
Sub Activity_Create(FirstTime As Boolean)

   Dim myLat As Double = 1.234d
   Dim myLon As Double = 5.678d
   
   'Test with android location object
   Dim J As JavaObject
   J.InitializeContext
   J.RunMethod("locationTest",Array(myLat,myLon))
   
   Dim myLocation As Location
   myLocation.Initialize
   myLocation.Latitude=myLat
   myLocation.Longitude=myLon
   Dim myLatSeconds As String = myLocation.ConvertToSeconds(myLocation.Latitude)
   Dim myLonSeconds As String = myLocation.ConvertToSeconds(myLocation.Longitude)
   
   Log("BA conversion is: "&myLatSeconds&"  "&myLonSeconds) 'throws 1:14:2,4  5:40:40,8
   
   Dim myLocationNew As Location
   myLocationNew.Initialize2(myLatSeconds,myLonSeconds)  'here it crashes

End Sub

#if JAVA
import android.location.Location;
public void locationTest(double mLat,double mLon){

  Location targetLocation = new Location("");//provider name is unnecessary
  targetLocation.setLatitude(mLat);
  targetLocation.setLongitude(mLon);
  String sLatsec = targetLocation.convert(targetLocation.getLatitude(),targetLocation.FORMAT_SECONDS);
  String sLonsec = targetLocation.convert(targetLocation.getLongitude(),targetLocation.FORMAT_SECONDS);

  BA.Log("Converted latitude is: " + sLatsec + "  " + sLonsec);  // <-- 1:14:2,4  5:40:40,8
}

#End If
 
  • Like
Reactions: udg
Upvote 0
Top