Create single value from Latitude and Longitude pair in PHP - php

I'm working on a Google Maps project within a PHP application. I need to find a way to store a latitude and longitude pair as a singular value. I'm using this to help store markers with identical coordinates.
Is there way I can encode the latitude/longitude pair into a single string? I would like something like:
$lat = 45.18392;
$long = 62.18293;
// Would return a single string like 893jfd8sj39k
$single_string = make_single_string($lat, $long);
function make_single_string($lat, $long)
{
// Do something here with $lat and $long
return $single_string;
}
The most important part of the function is that it must return the same string EVERY time.
Thanks for the help!

I think you are looking for this:
function make_single_string($lat, $long)
{
$single_string = md5( $lat.'-'.$long );
return $single_string;
}
result will be something like this:
04f59f6c007149079d0b5cc81ee0d25f

You can return a hash of both numbers:
function make_single_string($lat, $long)
{
return md5($lat.'-'.$long);
}

Cant you concatenate the string on the return? with .'s...
return $lat . "," . $long;

Is there a reason that you're not using an object for this?
$lat = 45.18392;
$long = 62.18293;
$pos = array(
'lat'=>$lat,
'long'=>$long
);
It's much more readable and as a bonus you don't have to parse it later (can be easily serialized as well).

If you want reversibility (and you probably do) then you need to come up with a standard input format. Assuming your latitude can go between +/-90, and your longitudes between +/-180, you could do something like:
Make sure the latitude and longitude have signs. If positive, prepend the + sign.
Zero-pad on the front to two digits (for latitude) and three digits (for longitude). 9.2 degrees of latitude would become +09.2.
Zero-pad on the end to however many significant digits you want (say, six). 9.2 degrees of latitude would then become +09.200000.
Convert +, -, and . to some kind of standard notation. Say, P for +, M for -, and d for .. For 9.2 degrees of latitude you'd get P09d200000.
Concatenate the latitude and longitude.
Then you get a string that's reversible and only has alphanumeric characters in it. You might not need something this fancy, though.

Why not just concat them?
$string = $lat . "-" . $long;
I mean if you really wanted to I supposed you could take the above and use md5 on it:
$string = md5($lat . "-" . $long);

What you're looking for really exists, and is not as simple as md5( $lat.'-'.$long );, as to be effective must be done before a process of generalization.
It´s called Geohash. In PHP there are different implementations. This is good, but Google offers several options.

Use a class or plain object.
class
class Coord {
public $lat;
public $long;
__construct($lat, $long) {
$this->lat = $lat;
$this->long = $long;
}
}
$coord = new Coord(45.18392, 62.18293);
echo $coord->lat;
echo $coord->long;
plain object
$coords = new stdClass();
$coords->lat = 45.18392;
$coords->long = 62.18293;
echo $coord->lat;
echo $coord->long;
If you needs to save these in a database, you could serialize the objects into a string, then unserialize as you pull them again from the database.
http://php.net/manual/en/function.serialize.php

Related

show number to 100 decimal places

As an example I have code similar to this:
$r1 = 7.39999999999999;
$r2 = 10000;
echo bcmul($r1,$r2,100);
//returns 74000.0
echo ($r1*$r2);
//returns 74000.0
I am wanting it to return 73999.9999999999 rather than rounding it off.
Is there a formula or function to do this?
The doc http://php.net/manual/de/function.bcmul.php says:
left_operand: The left operand, as a string.
right_operand: The right operand, as a string.
So use strings instead:
$r1 = "7.39999999999999";
$r2 = "10000";
echo bcmul($r1,$r2,100);
works.
Or if you have these varibales from somewhere cast them (via (string) ) to string. Maybe at this step you could encounter some roundings already...
I'm not a php person, but a quick Google suggests you may want the
$number_format()
function and specify the $decimals parameter. See this link

Couchbase with PHP GeoLocation Search - (Part) Solution

Problem
I was in need of a search by range of distance from latitude and longitude. This was relatively straight forward in SQL, however, in couchbase I came across some difficulty. I eventually discovered that spatial views offer a solution for this, however the spatial views aren't accessible via the PHP SDK (yet) and so you had to use the REST Api as an alternative.
Solution
I can get a result set within a range from a latitude and longitude using this method, but now need to sort by date created. Please see end of this post.
My documents are as such:
{
"docType" : "post",
"title" : "Test post",
"location" : {
"latitude" : 1.123456789
"longitude" : -13.9876543210
}
"created" : 1395329441
}
The trick is to create an index with a normal view which will format the keys in a specific way.
The formula
Preppend all keys with "point::"
Add a positive or negative sign "+", or "-"
Make the integer part 3 characters long by prepending with "0"s
Make the decimal part 9 characters long by appending with "0"
Repeat for both latitude and longitude
Example of a Key produced from the document above:
"point::+001.123456789,-013.987654321"
This will give you a key formatted in a way that will be sortable by the unicode collation which couchbase use.
The View
function (doc, meta) {
if(meta.type == "json" && doc.docType == "post" && doc.location){
if(doc.location.latitude && doc.location.longitude){
var prefix = "point::";
var latitude = doc.location.latitude.toString();
var longitude = doc.location.longitude.toString();
var pointKey = prefix.concat(buildKey(latitude), ",", buildKey(longitude));
emit(pointKey, meta.id);
function buildKey(coord){
// positive or negative sign
var sign;
if(coord.substring(0,1) == "-"){
sign = "-";
coord = coord.substring(1, coord.length);
} else {
sign = "+";
}
// remove "+" (incase it is there), though normall this isnt expressed
if(coord.substring(0,1) == "+"){
coord = coord.substring(1, coord.length);
}
var intSize = "000";
var decSize = "000000000";
// get integer and decimal parts of latitude
var parts = coord.split(".");
var int = parts[0];
var dec = parts[1];
// prepend int with 0's so it has a length of 3
if(int.length < intSize.length){
int = intSize.substring(0, intSize.length - int.length) + int;
}
int = int.substring(0,3);
// append dec with 0's so it has a length of 9
if(dec.length < decSize.length){
dec = dec + decSize.substring(0, decSize.length - dec.length);
}
dec = dec.substring(0,9);
return sign.concat(int, ".", dec);
}
}
}
}
The PHP
Now in PHP convert your latitude and longitude into a key in the same format. You can even work out a key for minimum latitude and minimum longitude and maximum latitude and maximum longitude so you can do a search by a "range" (Range will be a box not a circle, but good enough to narrow result set significantly)
For example:
$location = GeoLocation::fromDegrees($data['location']['latitude'], $data['location']['longitude']);
$coordinates = $location->boundingCoordinates(50, 'miles');
$startkey = "point::" . $location->buildKey($coordinates[0]->getLatitudeInDegrees()) . "," . $location->buildKey($coordinates[0]->getLongitudeInDegrees());
$endkey = "point::" . $location->buildKey($coordinates[1]->getLatitudeInDegrees()) . "," . $location->buildKey($coordinates[1]->getLongitudeInDegrees());
$viewOptions = array(
'startkey' => $startkey,
'endkey' => $endkey
);
$results = CBDatabase::$master->searchByView("dev_posts", "by_location", $viewOptions);
The build key function just follows the same rules as above in my view. and the GeoLocation class is taken from here: https://github.com/anthonymartin/GeoLocation.php
Request
I hope this really helps someone. It does work for me. If there is a much better way of doing this I'd love to hear constructive feedback.
I would now like to include a sort by date created within the range of keys. Order by Descending in the options won't work as this will order by the actual location key. The only way I can think of doing this is to include the date.created into the beginning of the key. But I'm not sure if this is the right way to go about this. I am very new to couchbase so guidance would be massively appreciated.

Convert string to integer and multiply two integers

I have a big time trying to either convert a string into a integer or multiply two integers. I can't convert the string into integer because it's resulting me into a boolean (when I'm using var_dump). I can convert the other integer in string, but I'm unable to multiply it.
I have this:
<? $fees=$commerce->cart->get_total();
$payfee = str_replace(' €', '', $fees);
$payfee = str_replace(',','', $payfee); //this is the string
$fee = 0.025;
$paypal = $payfee * $fee; //this thing is not working
?>
I tried converting the payfee in integer, but still can't make it work. I did something like this before and worked well, but not this time.
Any help will be appreciated.
P.S Thank you to the whole stackoverflow.com community which helped me many times before.
OP is running WooCommerce, and his $commerce->cart->get_total();
function responds output such as <span class="amount">560 €</span> (560 €)
and he's asking how to convert this to a number so he can get a fee
(2.5 %) from the amount.
First of all, the problem here is that the get_total() function responds with a string.
The correct way to fix this string would be a simple example such as
<?php
$totalAmountString = $commerce->cart->get_total(); //<span class="amount">560 €</span>
$totalAmountString = strip_tags($totalAmountString); //get rid of the span - we're left with "560 €"
$totalAmountString = str_replace(array(" €", ","), "", $totalAmountString);
$totalAmountFloat = (float)$totalAmountString;
$fee = 0.025;
$feeForThisAmount = $totalAmountFloat * $fee;
var_dump($feeForThisAmount);
$totalAmountWithFee = $totalAmountFloat + $feeForThisAmount;
var_dump($totalAmountWithFee);
?>
However, according to the Woo Commerce API Documentation you should be able to use $commerce->cart->total to get a float of the number, so a solution that might also work (again, I know nothing about WooCommerce), would be the following:
<?php
$totalAmountFloat = $commerce->cart->total;
$fee = 0.025;
$feeForThisAmount = $totalAmountFloat * $fee;
var_dump($feeForThisAmount);
$totalAmountWithFee = $totalAmountFloat + $feeForThisAmount;
var_dump($totalAmountWithFee);
?>
Edit
According to your latest data dump, the problem is that you're using
$paypal_fees=$woocommerce->cart->get_total() * 0.025;
where you should be using
$paypal_fees=$woocommerce->cart->total * 0.025;
as ->get_total() receives a string, and ->total receives a float.
try this
$integer =(int)$string;
LIve example
with var_dump() its correct
check this link
Use type casting like
$integer = (int)$myString;
then you can convert it to an integer,and its become easy to multiply
Use intval() function to covert string to integer
intval
From your elementary school technique based algorithm is posted here . You need not to convert string to integer in this case

How do I convert these coordinates to coordinates readable by Google Maps?

Take a look at the map coordinates on this page. This is linked in from Wikipedia and the coordinates are passed the query string. I'm not sure of the actual terms for this but How do I convert the coordinates? They look like this:
37° 14′ 6″ N, 115° 48′ 40″ W
I would like them to look like this:
37.235, -115.811111
, which is a format readable by Google maps, as seen in this example.
How do I do this in PHP, and what are the two different types of coordinates called?
The original format is in hours, minutes, seconds format. To convert to decimal, do:
D = H + M/60 + s/3600
So in your example, 37,14,6 becomes
37 + 14/60 + 6/3600 = 37.235, as stated.
If the latitude is N the result is positive, if S, negative.
If the longitude is E the result is positive. If west the result is negative.
Here is the Javascript function that does what you are talking about.
This utility permits the user to convert latitude and longitude
between decimal degrees and degrees, minutes, and seconds. For
convenience, a link is included to the National Geodetic Survey's
NADCON program, which allows conversions between the NAD83 / WGS84
coordinate system and the older NAD27 coordinate system. NAD27
coordinates are presently used for broadcast authorizations and
applications.
This utility requires that Javascript be enabled to perform the
calculations.
My PHP Code from this Post, Thank You!
function GetLatLon_FromExif($GPS){
$Lat_Ref = $GPS['GPSLatitudeRef'];
if($Lat_Ref == "S") { $Lat_Neg = "-"; }
$Lat_H = explode("/" ,$GPS['GPSLatitude']['0'])[0];
$Lat_M = explode("/" ,$GPS['GPSLatitude']['1'])[0];
$Lat_S = explode("/" ,$GPS['GPSLatitude']['2'])[0];
$Lat_S2 = explode("/" ,$GPS['GPSLatitude']['2'])[1];
$Lon_Ref = $GPS['GPSLongitudeRef'];
if($Lon_Ref == "W") { $Lon_Neg = "-"; }
$Lon_H = explode("/" ,$GPS['GPSLongitude']['0'])[0];
$Lon_M = explode("/" ,$GPS['GPSLongitude']['1'])[0];
$Lon_S = explode("/" ,$GPS['GPSLongitude']['2'])[0];
$Lon_S2 = explode("/" ,$GPS['GPSLongitude']['2'])[1];
$Lat = $Lat_H+($Lat_M/60)+(($Lat_S/$Lat_S2)/3600);
$Lon = $Lon_H+($Lon_M/60)+(($Lon_S/$Lon_S2)/3600);
return $Lat_Neg.$Lat.",".$Lon_Neg.$Lon;
}
JSON (from IMAGE EXIF):
"GPS": {
"GPSLatitudeRef": "N",
"GPSLatitude": [
"22/1",
"15/1",
"1708/100"
],
"GPSLongitudeRef": "W",
"GPSLongitude": [
"97/1",
"52/1",
"1882/100"
],
"GPSAltitudeRef": "\u0000",
"GPSAltitude": "9364/369",
"GPSSpeedRef": "K",
"GPSSpeed": "2203/12629",
"GPSImgDirectionRef": "T",
"GPSImgDirection": "52751/159",
"GPSDestBearingRef": "T",
"GPSDestBearing": "52751/159",
"UndefinedTag:0x001F": "6625/828"
}
Umm the page you mention already gives you the coordinates in WGS84 and in Latitude Longitude format

PHP String to Float

I am not familiar with PHP at all and had a quick question.
I have 2 variables pricePerUnit and InvoicedUnits. Here's the code that is setting these to values:
$InvoicedUnits = ((string) $InvoiceLineItem->InvoicedUnits);
$pricePerUnit = ((string) $InvoiceLineItem->PricePerUnit);
If I output this, I get the correct values. Lets say 5000 invoiced units and 1.00 for price.
Now, I need to show the total amount spent. When I multiply these two together it doesn't work (as expected, these are strings).
But I have no clue how to parse/cast/convert variables in PHP.
What should I do?
$rootbeer = (float) $InvoicedUnits;
Should do it for you. Check out Type-Juggling. You should also read String conversion to Numbers.
You want the non-locale-aware floatval function:
float floatval ( mixed $var ) - Gets the float value of a string.
Example:
$string = '122.34343The';
$float = floatval($string);
echo $float; // 122.34343
Well, if user write 1,00,000 then floatvar will show error. So -
floatval(preg_replace("/[^-0-9\.]/","",$input));
This is much more reliable.
Usage :
$input = '1,03,24,23,434,500.6798633 this';
echo floatval(preg_replace("/[^-0-9\.]/","",$input));
Dealing with markup in floats is a non trivial task. In the English/American notation you format one thousand plus 46*10-2:
1,000.46
But in Germany you would change comma and point:
1.000,46
This makes it really hard guessing the right number in multi-language applications.
I strongly suggest using Zend_Measure of the Zend Framework for this task. This component will parse the string to a float by the users language.
you can follow this link to know more about How to convert a string/number into number/float/decimal in PHP.
HERE IS WHAT THIS LINK SAYS...
Method 1: Using number_format() Function. The number_format() function is used to convert a string into a number. It returns the formatted number on success otherwise it gives E_WARNING on failure.
$num = "1000.314";
//Convert string in number using
//number_format(), function
echo number_format($num), "\n";
//Convert string in number using
//number_format(), function
echo number_format($num, 2);
Method 2: Using type casting: Typecasting can directly convert a string into a float, double, or integer primitive type. This is the best way to convert a string into a number without any function.
// Number in string format
$num = "1000.314";
// Type cast using int
echo (int)$num, "\n";
// Type cast using float
echo (float)$num, "\n";
// Type cast using double
echo (double)$num;
Method 3: Using intval() and floatval() Function. The intval() and floatval() functions can also be used to convert the string into its corresponding integer and float values respectively.
// Number in string format
$num = "1000.314";
// intval() function to convert
// string into integer
echo intval($num), "\n";
// floatval() function to convert
// string to float
echo floatval($num);
Method 4: By adding 0 or by performing mathematical operations. The string number can also be converted into an integer or float by adding 0 with the string. In PHP, performing mathematical operations, the string is converted to an integer or float implicitly.
// Number into string format
$num = "1000.314";
// Performing mathematical operation
// to implicitly type conversion
echo $num + 0, "\n";
// Performing mathematical operation
// to implicitly type conversion
echo $num + 0.0, "\n";
// Performing mathematical operation
// to implicitly type conversion
echo $num + 0.1;
Use this function to cast a float value from any kind of text style:
function parseFloat($value) {
return floatval(preg_replace('#^([-]*[0-9\.,\' ]+?)((\.|,){1}([0-9-]{1,3}))*$#e', "str_replace(array('.', ',', \"'\", ' '), '', '\\1') . '.\\4'", $value));
}
This solution is not dependant on any locale settings. Thus for user input users can type float values in any way they like. This is really helpful e.g. when you have a project wich is in english only but people all over the world are using it and might not have in mind that the project wants a dot instead of a comma for float values.
You could throw javascript in the mix and fetch the browsers default settings but still many people set these values to english but still typing 1,25 instead of 1.25 (especially but not limited to the translation industry, research and IT)
I was running in to a problem with the standard way to do this:
$string = "one";
$float = (float)$string;
echo $float; : ( Prints 0 )
If there isn't a valid number, the parser shouldn't return a number, it should throw an error. (This is a condition I'm trying to catch in my code, YMMV)
To fix this I have done the following:
$string = "one";
$float = is_numeric($string) ? (float)$string : null;
echo $float; : ( Prints nothing )
Then before further processing the conversion, I can check and return an error if there wasn't a valid parse of the string.
For the sake of completeness, although this question is ancient, it's worth mentioning the filter_var() set of functions, which should not only handle the formatting bits itself, but also validate or sanitise the output, thus being safer to use in the context of a form being filled in by users (or, eventually, a database that might have some corrupted/inconsistent fields):
$InvoicedUnits = (float) filter_var($InvoiceLineItem->InvoicedUnits,
FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION));
$pricePerUnit = (float) filter_var($InvoiceLineItem->PricePerUnit,
FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION));
printf("The total is: %.2f\n", $InvoicedUnits * $pricePerUnit); // both are now floats and the result is a float, formatted to two digits after the decimal sign.
This sanitises the output (which will still remain a string) and will accept the current locale's setting of the decimal separator (e.g. dot vs. comma); also, there are more options on the PHP manual for validation (which will automatically convert the result to a float if valid). The results will be slightly different for different scenarios — e.g. if you know in advance that the $InvoiceLineItem will only have valid digits and symbols for floating-point numbers, or if you need to 'clean up' the field first, getting rid of whitespace, stray characters (such as currency symbols!), and so forth.
Finally, if you wish to have nicely-formatted output — since the total is expressed in a currency — you should also take a look at the built-in NumberFormatter class, and do something like:
$InvoicedUnits = (float) filter_var($InvoiceLineItem->InvoicedUnits,
FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION));
$pricePerUnit = (float) filter_var($InvoiceLineItem->PricePerUnit,
FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION));
$fmt = new NumberFormatter('de_DE', NumberFormatter::CURRENCY);
echo 'Total is: ' . $fmt->formatCurrency($InvoicedUnits * $pricePerUnit, 'EUR') . PHP_EOL;
This will also handle thousand separators (spaces, dots, commas...) according to the configured locale, and other similar fancy things.
Also, if you wish, you can use '' (the empty string) for the default locale string (set either by the server or optionally by the browser) and $fmt->getSymbol(NumberFormatter::INTL_CURRENCY_SYMBOL) to get the default 3-letter currency code (which might not be what you want, since usually prices are given in a specific currency — these functions do not take currency exchange rates into account!).
If you need to handle values that cannot be converted separately, you can use this method:
try {
// use + 0 if you are accounting in cents
$doubleValue = trim($stringThatMightBeNumeric) + 0.0;
} catch (\Throwable $th) {
// bail here if you need to
}

Categories