Gauss-Boaga to WGS84 - php

I'm trying to convert some coordinates from Gauss-Boaga to WGS84. Here's what I've done (PHP):
function gaussToLatLng($Eutm, $Nutm){
// parametri che dipendono dal fuso ovest
$l0 = 9;
$fraz = $Nutm/111092.0821;
echo "$fraz ";
$A= $fraz +
(0.1449300705 * sin(deg2rad(2*$fraz))) +
(0.0002138508 * sin(deg2rad(4*$fraz))) +
(0.0000004322 * sin(deg2rad(6*$fraz)));
$v = sqrt(1 + (0.0067681702 * cos(deg2rad($A)) * cos(deg2rad($A)) ) );
$y = $Eutm - 500000;
$B = rad2deg(atan( ($v * sinh(deg2rad($y/6397376.633)) ) / cos(deg2rad($A))));
$lng = rad2deg(atan(tan(deg2rad($A)) * cos(deg2rad($v * $B))));
$lat = $B + $l0;
echo "A=$A, B=$B \n";
return array(
'lat' => $lat,
'lng' => $lng
);
}
Using as input (1517140, 5036970), I get (9.2271558768758 45.485183518206) while with this online tool I calculated that I should have (9.2189597, 45.4859253) (about 1 Km of difference).
Could you help me spot the error in my code?

Solved using a PHP library: proj4php, using the definition for Gauss Boaga fuso Ovest found here.
Those guys are awesome!

Related

How to put a list of results obtained from the database into a send message telegram bot

I want to know how to put a list of results obtained from the database into a send message method in telegram bot with php?
Similar to this picture
Actually, this bot is an anonymous chat bot with which you can also find people near you and chat with them, and I want when the user clicks on the button (show people near me), all the people near the user based on latitude and longitude and take the information of nearby users from the database and put it in a sendMessage method.
function show_all_near_people ($user_id) {
$db = Db::getInstance();
$user_info = $db->query("SELECT * FROM chat_nashenas WHERE user_id=:user_id", array(
"user_id" => $user_id));
$user_latitude = $user_info[0][latitude];
$user_longitude = $user_info[0][longitude];
$users_info = $db->query("SELECT * FROM chat_nashenas");
for ($i = 1; $i <= count($users_info); $i++) {
$theta = $user_longitude - $users_info[$i][longitude];
$dist = sin(deg2rad($user_latitude)) * sin(deg2rad($users_info[$i][latitude])) + cos(deg2rad($user_latitude)) * cos(deg2rad($users_info[$i][latitude])) * cos(deg2rad($theta));
$dist = acos($dist);
$dist = rad2deg($dist);
$miles = $dist * 60 * 1.1515;
$distance = ($miles * 1.609344);
if ($distance <= 30 && $distance >= 1) {
${"distancetokm$i"} = "🏁 ".round($distance)."km";
$sex = $users_info[$i][sex];
${"first_name$i"} = $users_info[$i][first_name];
${"unique_id$i"} = $users_info[$i][unique_id];
${"age$i"} = $users_info[$i][age];
${"province$i"} = $users_info[$i][province];
${"city$i"} = $users_info[$i][city];
if ($sex == 2) {
${"sex$i"} = "🙍🏻‍♂️";
}
else if ($sex == 1) {
${"sex$i"} = "🙎🏻‍♀️";
}
}
else if ($distance < 1) {
$distancetom = $distance * 1000;
${"distancetom$i"} = "🏁 ".round($distancetom)."m";
$sex = $users_info[$i][sex];
${"first_name$i"} = $users_info[$i][first_name];
${"unique_id$i"} = $users_info[$i][unique_id];
${"age$i"} = $users_info[$i][age];
${"province$i"} = $users_info[$i][province];
${"city$i"} = $users_info[$i][city];
if ($sex == 2) {
${"sex$i"} = "🙍🏻‍♂️";
}
else if ($sex == 1) {
${"sex$i"} = "🙎🏻‍♀️";
}
}
}
MessageRequestJson("sendMessage", array(chat_id => $user_id, text => "🛰 لیست افراد نزدیک به شما.
1 . $sex1 $first_name1 $unique_id1
$age1 $province1 ($city1) ($distancetokm1)
〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️
2 . $sex2 $first_name2 $unique_id2
$age2 $province2 ($city2) ($distancetokm2)
〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️〰️
3 . $sex3 $first_name3 $unique_id3
$age3 $province3 ($city3) ($distancetokm3)"));
}
This is the code I wrote. But this code is very wrong. I have to say that however many close users found in the database, it will show all 10 people on one page, and then the user will be shown the next page by clicking the inline button (next page).
If I put the method of sendMessage inside the for loop, a message will be sent for each user found, if I want the list of all found users to be sent in the form of a message like the picture.
I hope I was able to understand what I meant.
Thank you so much for your help.

How to calculate NPER in PHP

I can't figure out how to calculate NPER in php.
I did not find any article in google.
I'm very weak in math becouse of it i'm asking for help.
This is what i did so far :(
public function Nper($interest, $payment, $loan){
$nperC = Log10($payment/($payment+$loan+$interest))/Log10(1+$interest);
return $nperC;
}
if(isset($_POST['NperSubmit'])){
$calc = new CalculatorModel();
$months = $calc->Nper($_POST['interest'], $_POST['payment'], $_POST['loan']);
echo round($months,2);
}
Working code (From Tijo John answer)
public function Nper($interest, $payment, $loan){
$interest = $interest / 1200;
$nperC = Log10 ($payment/ ($payment- $loan * $interest)) / Log10(1 + $interest);
return $nperC;
}
$calc = new CalculatorModel();
$months = $calc->Nper($_POST['interest'], $_POST['payment'], $_POST['loan']);
echo round($months,2);
Thanks :))
I think you should have change the formula as follows
Log10 ($payment/ ($payment- $loan * $interest)) / Log10(1 + $interest)

polygon matrix calculation for viscosity matrix

I am writing a program which needs different value of gas viscosity at different temperature for respective gases. Data which i have is given below. I am new in programming in php . can anyone please give me the logic behind it. so that i can get viscosity at any required tempertaure through the program. thanks
Data for viscosity calculation (dyn. visc. [Ns/m² = kg/ms]; Source: VDI Wärmeatlas
Temp. [°C] 0 100 200 300 400 500
CO2 1,37E-05 1,82E-05 2,22E-05 2,59E-05 2,93E-05 3,24E-05
O2 1,92E-05 2,43E-05 2,88E-05 3,29E-05 3,67E-05 4,03E-05
H2O 9,00E-06 1,25E-05 1,61E-05 1,97E-05 2,33E-05 2,69E-05
N2 1,66E-05 2,09E-05 2,47E-05 2,82E-05 3,14E-05 3,42E-05
You can easily fit your data in Excel. Here's a plot that shows the result, along with the 2nd order polynomial:
Finally I got the right answer. In case if anyone need it, I am posting it out here:
class baseViscosityCalc {
public $arViscosity = array(
array(0, 1.37e-05, 1.92e-05, 9.00e-06, 1.66e-05),
array(100, 1.82e-05, 2.43e-05, 1.25e-05, 2.09e-05),
array(200, 2.22e-05, 2.88e-05, 1.61e-05, 2.47e-05),
array(300, 2.59e-05, 3.29e-05, 1.97e-05, 2.82e-05),
array(400, 2.93e-05, 3.67e-05, 2.33e-05, 3.14e-05),
array(500, 3.24e-05, 4.03e-05, 2.69e-05, 3.42e-05)
);
public function getViscosityData($DCat) {
$arValue = array(
'Temperature' => 0.0,
'CO2' => 0.0,
'O2' => 0.0,
'H2O' => 0.0,
'N2' => 0.0
);
for ($i = 0; $i < count($this->arViscosity); $i++) {
$arValue['Temperature'] = $DCat;
if ($DCat < $this->arViscosity[0][0]) {
$arValue['CO2'] = $this->arViscosity[0][1];
$arValue['O2'] = $this->arViscosity[0][2];
$arValue['H2O'] = $this->arViscosity[0][3];
$arValue['N2'] = $this->arViscosity[0][4];
break;
}
if ($DCat > $this->arViscosity[count($this->arViscosity) - 1][0]) {
$arValue['CO2'] = $this->arViscosity[count($this->arViscosity) - 1][1];
$arValue['O2'] = $this->arViscosity[count($this->arViscosity) - 1][2];
$arValue['H2O'] = $this->arViscosity[count($this->arViscosity) - 1][3];
$arValue['N2'] = $this->arViscosity[count($this->arViscosity) - 1][4];
breaK;
}
if ($DCat > $this->arViscosity[$i][0] && $DCat < $this->arViscosity[$i + 1][0]) {
$factor = ($DCat - $this->arViscosity[$i][0]) / ($this->arViscosity[$i + 1][0] - $this->arViscosity[$i][0]);
$arValue['CO2'] = $factor * ($this->arViscosity[$i + 1][1] - $this->arViscosity[$i][1]) + $this->arViscosity[$i][1];
$arValue['O2'] = $factor * ($this->arViscosity[$i + 1][2] - $this->arViscosity[$i][2]) + $this->arViscosity[$i][2];
$arValue['H2O'] = $factor * ($this->arViscosity[$i + 1][3] - $this->arViscosity[$i][3]) + $this->arViscosity[$i][3];
$arValue['N2'] = $factor * ($this->arViscosity[$i + 1][4] - $this->arViscosity[$i][4]) + $this->arViscosity[$i][4];
break;
}
}
return $arValue;
}
}

Reading Geotag data from image in php

Does anyone know if there is a way to read geotag data from photos in PHP?
Thanks
Like everyone else has said, exif_read_data(); will do it.
To go ahead and get all of the data, use these args:
exif_read_data($img, 0, true); // where $img is the path to your image
This function can only read headers from tiffs and jpegs and I'm pretty sure only jpegs may contain geotags. I've written a simple php script for use in the command line and posted it as a gist on github.
Run the script like this: php exif.php
It will echo out an array. Look for the coordinates here:
[GPS] => Array
[GPSLatitudeRef] => N
[GPSLatitude] => Array
[0] => 30/1
[1] => 1589/100
[2] => 0/1
[GPSLongitudeRef] => W
[GPSLongitude] => Array
[0] => 87/1
[1] => 3609/100
[2] => 0/1
[GPSAltitudeRef] =>
[GPSAltitude] => 18289/454
[GPSTimeStamp] => Array
[0] => 20/1
[1] => 22/1
[2] => 2065/1
[GPSImgDirectionRef] => T
[GPSImgDirection] => 34765/689
The Latitude and Longitude arrays contain three values: 0 is for degrees, 1 is for minutes and 2 is for seconds. If you see something like "1589/100" this is equal to 15.89. So for the GPSLongitude array, 3609/100 is equal to 36.09.
Convert the coordinates from degrees-minutes-second form to decimal form here http://www.satsig.net/degrees-minutes-seconds-calculator.htm
If the latitude is South, dont forget to make it negative. If the longitude is west, make that negative. The coodinates from the above data are: 30.26483, -87.6015
Will Coughlin's answer is correct though I formulated a function for quick reference in case someone stumbles upon the same problem.
/**
* Returns an array of latitude and longitude from the Image file
* #param image $file
* #return multitype:number |boolean
*/
function read_gps_location($file){
if (is_file($file)) {
$info = exif_read_data($file);
if (isset($info['GPSLatitude']) && isset($info['GPSLongitude']) &&
isset($info['GPSLatitudeRef']) && isset($info['GPSLongitudeRef']) &&
in_array($info['GPSLatitudeRef'], array('E','W','N','S')) && in_array($info['GPSLongitudeRef'], array('E','W','N','S'))) {
$GPSLatitudeRef = strtolower(trim($info['GPSLatitudeRef']));
$GPSLongitudeRef = strtolower(trim($info['GPSLongitudeRef']));
$lat_degrees_a = explode('/',$info['GPSLatitude'][0]);
$lat_minutes_a = explode('/',$info['GPSLatitude'][1]);
$lat_seconds_a = explode('/',$info['GPSLatitude'][2]);
$lng_degrees_a = explode('/',$info['GPSLongitude'][0]);
$lng_minutes_a = explode('/',$info['GPSLongitude'][1]);
$lng_seconds_a = explode('/',$info['GPSLongitude'][2]);
$lat_degrees = $lat_degrees_a[0] / $lat_degrees_a[1];
$lat_minutes = $lat_minutes_a[0] / $lat_minutes_a[1];
$lat_seconds = $lat_seconds_a[0] / $lat_seconds_a[1];
$lng_degrees = $lng_degrees_a[0] / $lng_degrees_a[1];
$lng_minutes = $lng_minutes_a[0] / $lng_minutes_a[1];
$lng_seconds = $lng_seconds_a[0] / $lng_seconds_a[1];
$lat = (float) $lat_degrees+((($lat_minutes*60)+($lat_seconds))/3600);
$lng = (float) $lng_degrees+((($lng_minutes*60)+($lng_seconds))/3600);
//If the latitude is South, make it negative.
//If the longitude is west, make it negative
$GPSLatitudeRef == 's' ? $lat *= -1 : '';
$GPSLongitudeRef == 'w' ? $lng *= -1 : '';
return array(
'lat' => $lat,
'lng' => $lng
);
}
}
return false;
}
Hope it helps someone.
Call this function with filename. I testet it and it works prefectly.
Call example:
$fileName='xxxxxx'; //or $fileName='xxxxxxxxx';
echo $returned_data = triphoto_getGPS($fileName);
Function:
function triphoto_getGPS($fileName)
{
//get the EXIF all metadata from Images
$exif = exif_read_data($fileName);
if(isset($exif["GPSLatitudeRef"])) {
$LatM = 1; $LongM = 1;
if($exif["GPSLatitudeRef"] == 'S') {
$LatM = -1;
}
if($exif["GPSLongitudeRef"] == 'W') {
$LongM = -1;
}
//get the GPS data
$gps['LatDegree']=$exif["GPSLatitude"][0];
$gps['LatMinute']=$exif["GPSLatitude"][1];
$gps['LatgSeconds']=$exif["GPSLatitude"][2];
$gps['LongDegree']=$exif["GPSLongitude"][0];
$gps['LongMinute']=$exif["GPSLongitude"][1];
$gps['LongSeconds']=$exif["GPSLongitude"][2];
//convert strings to numbers
foreach($gps as $key => $value){
$pos = strpos($value, '/');
if($pos !== false){
$temp = explode('/',$value);
$gps[$key] = $temp[0] / $temp[1];
}
}
//calculate the decimal degree
$result['latitude'] = $LatM * ($gps['LatDegree'] + ($gps['LatMinute'] / 60) + ($gps['LatgSeconds'] / 3600));
$result['longitude'] = $LongM * ($gps['LongDegree'] + ($gps['LongMinute'] / 60) + ($gps['LongSeconds'] / 3600));
$result['datetime'] = $exif["DateTime"];
return $result;
}
}
You can use the EXIF functions of PHP:
exif_read_data($file);
You can use the exif_read_data() function if the geotag data is embedded in the EXIF data.
Install Intervention\Image by following command.
Reference: http://image.intervention.io/getting_started/installation
composer require intervention/image
Update config/app.php
'providers' => [
Intervention\Image\ImageServiceProvider::class
],
'aliases' => [
'Image' => Intervention\Image\Facades\Image::class
]
Use Library:
$data = Image::make(public_path('IMG.jpg'))->exif();
if(isset($data['GPSLatitude'])) {
$lat = eval('return ' . $data['GPSLatitude'][0] . ';')
+ (eval('return ' . $data['GPSLatitude'][1] . ';') / 60)
+ (eval('return ' . $data['GPSLatitude'][2] . ';') / 3600);
$lng = eval('return ' . $data['GPSLongitude'][0] . ';')
+ (eval('return ' . $data['GPSLongitude'][1] . ';') / 60)
+ (eval('return ' . $data['GPSLongitude'][2] . ';') / 3600);
echo "$lat, $lng";
} else {
echo "No GPS Info";
}

calculate tile size of google map at zoom level n

Hey. I have a maps application that uses google maps. I get the bounds off the map, and then I do some clustering markers on that grounds, but to be able to have the clusters stay at the same place, I'd like to know how to make the boundaries that I pass snap into the tilegrid that google uses. The quadtree algorithm they use for their map essentially what I'm asking for is
how do I get the bounds for the tiles that the viewport is in. I've tried to illustrate it :)
If I do the cluster calc on the tile bounds and not the viewport, when I split it up in a grid, the clusters will stay in the same place, because the grid will be absolute at each zoom level.
Also this allows for better query caching, as the queries will be a lot similar when the bounds have to "snap in" to the tiles, AND the user will be able to pan with markers in proximity being displayed already.
UPDATE
I'm starting over...
I've got this
function TileMyBounds($sx, $sy, $nx, $ny, $zoom)
{
function TileMyBounds($sx, $sy, $nx, $ny, $zoom)
{
list($nmx,$nmy) = $this->LatLonToMeters($ny/1000000, $nx/1000000);
list($ntx, $nty) = $this->MetersToTile($nmx, $nmy, $zoom);
$nbounds = $this->TileLatLonBounds($ntx, $nty, $zoom);
list($smx,$smy) = $this->LatLonToMeters($sy/1000000, $sx/1000000);
list($stx, $sty) = $this->MetersToTile($smx, $smy, $zoom);
$sbounds = $this->TileLatLonBounds($stx, $sty, $zoom);
$step = ($sbounds[3]-$sbounds[1])*1000000;
return array($sbounds[0]*1000000, $sbounds[1]*1000000, $nbounds[2]*1000000, $nbounds[3]*1000000, $step);
}
and the function where I use it looks like this:
function clusterGrid($zoom,$nelt,$nelg,$swlt,$swlg)
{
$singlemarkers = array();
$clusters = array();
list($swlg, $swlt, $nelg, $nelt, $step) = $this->TileMyBounds($swlg, $swlt, $nelg, $nelt, $zoom);
$calcbounds = $this->TileMyBounds($swlg, $swlt, $nelg, $nelt, $zoom);
$queryconcat = "";
$length_lng = ceil(($nelg-$swlg)/$step);
$length_lat = ceil(($nelt-$swlt)/$step);
$orgnelg = $nelg;
$orgswlt = $swlt;
for($i=0;$i < $length_lng + 1; $i++) {
$nelg -= $step;
$temp_swlt = $swlt;
for($j=0; $j < $length_lat + 1; $j++) {
$temp_swlt += $step;
if($nelg > $orgnelg) continue;
if($temp_swlt > $nelt) continue;
if($nelg < $swlg) continue;
if($temp_swlt < $orgswlt) continue;
$q = $this->db->select('
COUNT(*) AS CO,
(MAX(lat)+MIN(lat))/2 AS lat,
(MAX(lng)+MIN(lng))/2 AS lng')
->where('`lat` BETWEEN '.$temp_swlt.' AND '.($temp_swlt+$step).' AND
`lng` BETWEEN '.($nelg-$step).' AND '.$nelg)
->get('markers');
$queryconcat += $this->db->last_query();
$result = $q->row_array();
if($result['CO'] == 0) {
continue;
}
$clusters[] = array('lat' => ($result['lat']), 'lng' => ($result['lng']), 'size' => $result['CO']);
}
}
return array('singlemarkers' => '', 'clustermarkers' => $clusters, 'bounds' => $calcbounds, 'lengths' => array($length_lng, $length_lat));
}
UPDATE!!!! 12/03/2011 - Almost there
The tiles are somewhat precise, yet not entirely, so when panning around, the clusters can "move around" a little. Due to the fact that the $step = ($sbounds[3]-$sbounds[1])*1000000; calculation is not always the same at each zoom level, as I would've expected because I would think that a tile would have the same width and length in lat and lon as any other tile at the same zoom level.
But something's not quite right. Can anyone tell why I'm not getting the viewport coordinates when I pass in swlg,swlat,nelg,nelat and the zoom level
You want to solve the space-filling-curve equation first with all 4 bounds coordinates.
list($lng, $lat) = array ($row['lng'], $row['lat']);
list($mx, $my) = $mercator->LatLonToMeters($lat, $lng);
list($tx, $ty) = $mercator->MetersToTile($mx, $my, MAXZOOM);
list($tx, $ty) = array ($tx, ((1 << MAXZOOM) - 1) - $ty );
list($minx, $miny) = $this->PixelsToMeters( $tx*$this->tileSize, $ty*$this->tileSize, $zoom );
list($maxx, $maxy) = $this->PixelsToMeters( ($tx+1)*$this->tileSize, ($ty+1)*$this->tileSize, $zoom );
return array($minx, $miny, $maxx, $maxy);
or
list($lng, $lat) = array ($row['lng'], $row['lat']);
list($mx, $my) = $mercator->LatLonToMeters($lat, $lng);
list($tx, $ty) = $mercator->MetersToTile($mx, $my, MAXZOOM);
list($tx, $ty) = array ($tx, ((1 << MAXZOOM) - 1) - $ty );
$bounds = $this->TileBounds($tx, $ty, $zoom);
list($minLat, $minLon) = $this->MetersToLatLon($bounds[0], $bounds[1]);
list($maxLat, $maxLon) = $this->MetersToLatLon($bounds[2], $bounds[3]);
return array($minLat, $minLon, $maxLat, $maxLon);
EDIT: Problem is solved. OP answered in private Mail:

Categories