| Geo-Coordinates-VandH documentation | Contained in the Geo-Coordinates-VandH distribution. |
Geo::Coordinates::VandH - Convert and Manipulate telco V and H coordinates
use Geo::Coordinates::VandH; $blah=new Geo::Coordinates::VandH; ($lat,$lon) = $blah->vh2ll(5498,2895); printf "%lf,%lf\n",$lat,$lon; To find the mileage between 5498,2895 and 5527,2873 in miles: use Geo::Coordinates::VandH; $blah=new Geo::Coordinates::VandH; printf "Distance between Pontiac, MI and Southfield, MI is approximately: %d miles\n",$blah->distance(5498,2895,5527,2873);
Currently this package supports the translation of V+H to Lat/Long, and mileage calculations between two V+H coordinates.
Results are returned in decimal degrees for V+H to Lat/Long, and Miles for distance.
Future versions will convert Lat/Long to V+H coordinates.
Paul Timmins, <paul@timmins.net>
perl.
| Geo-Coordinates-VandH documentation | Contained in the Geo-Coordinates-VandH distribution. |
package Geo::Coordinates::VandH; use strict; use Math::Trig; use Math::Complex; #fixes a few one-off problems with negative square roots use vars qw($VERSION); $VERSION = '1.11'; sub new { my $package = shift; return bless({}, $package); }; sub distance { my $self = shift; my $v1; my $h1; my $v2; my $h2; my $miles; my $vd; my $hd; my $sum; my $count; ($v1,$h1,$v2,$h2) = @_; $vd=$v1-$v2; if ($vd < 0) { $vd=$vd*-1; }; $hd=$h1-$h2; if ($hd < 0) { $hd=$hd*-1; }; $vd=$vd/3; $hd=$hd/3; $count=1; while (($vd**2+$hd**2) > 1777) { $vd=$vd/3; $hd=$hd/3; $count++; }; $sum=$vd**2+$hd**2; $sum = $sum * ( 0.1 * (9**$count)); $miles=sqrt($sum); #round up to next greatest mile if (($miles-int($miles)) > 0) { $miles=int($miles)+1; }; return $miles; }; sub vh2ll { my $self = shift; #Constants shamelessly stolen from vh2ll.c my $m_pi=3.14159265358979323846; my $transv=6363.235; my $transh=2250.7; my $rotc=0.23179040; my $rots=0.97276575; my $radius=12481.103; my $ex=0.40426992; my $ey=0.68210848; my $ez=0.60933887; my $wx=0.65517646; my $wy=0.37733790; my $wz=0.65449210; my $px=-0.555977821730048699; my $py=-0.345728488161089920; my $pz=0.755883902605524030; my $gx=0.216507961908834992; my $gy=-0.134633014879368199; my $a=0.151646645621077297; my $q=-0.294355056616412800; my $q2=0.0866448993556515751; my @bi = ( 1.00567724920722457, -0.00344230425560210245, 0.000713971534527667990, -0.0000777240053499279217, 0.00000673180367053244284, -0.000000742595338885741395, 0.0000000905058919926194134 ); my $x; my $y; my $z; my $v; my $h; my $delta; ($v,$h) = @_; my $t1 = ($v - $transv) / $radius; my $t2 = ($h - $transh) / $radius; my $vhat = $rotc*$t2 - $rots*$t1; my $hhat = $rots*$t2 + $rotc*$t1; my $e = cos(sqrt($vhat*$vhat + $hhat*$hhat)); my $w = cos(sqrt($vhat*$vhat + ($hhat-0.4)*($hhat-0.4))); my $fx = $ey*$w - $wy*$e; my $fy = $ex*$w - $wx*$e; my $b = $fx*$gx + $fy*$gy; my $c = $fx*$fx + $fy*$fy - $q2; my $disc = $b*$b - $a*$c; #discriminant if ($disc == 0.0) { #It's right on the E-W axis $z = $b/$a; $x = ($gx*$z - $fx)/$q; $y = ($fy - $gy*$z)/$q; } else { $delta = sqrt($disc); $z = ($b + $delta)/$a; $x = ($gx*$z - $fx)/$q; $y = ($fy - $gy*$z)/$q; if ( $vhat * ( $px*$x + $py*$y + $pz*$z) < 0 ) { #wrong direction $z = ($b - $delta)/$a; $x = ($gx*$z - $fx)/$q; $y = ($fy - $gy*$z)/$q; }; }; my $lat=asin($z); #Use polynomial approximation for inverse mapping #(sphere to spheroid) my $lat2 = $lat*$lat; my $earthlat = 0; for (my $i=6; $i>=0 ; $i--) { $earthlat = ($earthlat + $bi[$i]) * ($i? $lat2 : $lat); }; $earthlat *= 180/$m_pi; # Adjust Longitude by 52 degrees my $lon = atan2($x,$y) * 180/$m_pi; my $earthlon = $lon + 52.0000000000000000; return ($earthlat,$earthlon); }; 1; __END__ # Below is stub documentation for your module. You better edit it!