File Coverage

blib/lib/Religion/Islam/Qibla.pm
Criterion Covered Total %
statement 12 75 16.0
branch 0 18 0.0
condition 0 9 0.0
subroutine 4 14 28.5
pod 0 10 0.0
total 16 126 12.7


line stmt bran cond sub pod time code
1             # Copyright Infomation
2             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3             # Author : Dr. Ahmed Amin Elsheshtawy, Ph.D.
4             # Website: http://www.mewsoft.com
5             # Email : support@mewsoft.com
6             # Copyrights (c) 2000-2015 Mewsoft Corporation. All rights reserved.
7             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8             package Religion::Islam::Qibla;
9              
10 1     1   17434 use Carp;
  1         1  
  1         83  
11 1     1   4 use strict;
  1         1  
  1         30  
12 1     1   3 use warnings;
  1         5  
  1         24  
13 1     1   1617 use Math::Trig;
  1         21059  
  1         1157  
14              
15             our $VERSION = '4.0';
16             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
17             sub new {
18 0     0 0   my ($class, %args) = @_;
19 0           my $self = bless {}, $class;
20             # Default destination point is the Kabah Lat=21 Deg N, Long 40 Deg E
21 0 0         $self->{DestLat} = $args{DestLat}? $args{DestLat}: 21.423333; # 21.423333;
22 0 0         $self->{DestLong} = $args{DestLong}? $args{DestLong}: 39.823333; # 39.823333;
23 0           return $self;
24             }
25             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26             sub DestLat {
27 0     0 0   my ($self) = shift;
28 0 0         $self->{DestLat} = shift if @_;
29 0           return $self->{DestLat};
30             }
31             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
32             sub DestLong {
33 0     0 0   my ($self) = shift;
34 0 0         $self->{DestLong} = shift if @_;
35 0           return $self->{DestLong};
36             }
37             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
38             #Converting from Degrees, Minutes and Seconds to Decimal Degrees
39             sub DegreeToDecimal {
40 0     0 0   my ($self, $degrees, $minutes, $seconds) = @_;
41 0           return $degrees + ($minutes / 60) + ($seconds / 3600);
42             }
43             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
44             #Converting from Decimal Degrees to Degrees, Minutes and Seconds
45             sub DecimalToDegree {
46 0     0 0   my ($self, $decimal_degree) = @_;
47 0           my ($degrees, $minutes, $seconds, $ff);
48            
49 0           $degrees = int($decimal_degree);
50 0           $ff = $decimal_degree - $degrees;
51 0           $minutes = int(60 * $ff);
52 0           $seconds = 60 * ((60 * $ff) - $minutes);
53 0           return ($degrees, $minutes, $seconds);
54             }
55             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
56             # The shortest distance between points 1 and 2 on the earth's surface is
57             # d = arccos{cos(Dlat) - [1 - cos(Dlong)]cos(lat1)cos(lat2)}
58             # Dlat = lab - lat2
59             # Dlong = 10ng - long2
60             # lati, = latitude of point i
61             # longi, = longitude of point i
62              
63             #Conversion of grad to degrees is as follows:
64             #Grad=400-degrees/0.9 or Degrees=0.9x(400-Grad)
65              
66             #Latitude is determined by the earth's polar axis. Longitude is determined
67             #by the earth's rotation. If you can see the stars and have a sextant and
68             #a good clock set to Greenwich time, you can find your latitude and longitude.
69              
70             # one nautical mile equals to:
71             # 6076.10 feet
72             # 2027 yards
73             # 1.852 kilometers
74             # 1.151 statute mile
75              
76             # Calculates the distance between any two points on the Earth
77             sub GreatCircleDistance {
78 0     0 0   my ($self, $orig_lat , $dest_lat, $orig_long, $dest_long) = @_;
79 0           my ($d, $l1, $l2, $i1, $i2);
80            
81 0           $l1 = deg2rad($orig_lat);
82 0           $l2 = deg2rad($dest_lat);
83 0           $i1 = deg2rad($orig_long);
84 0           $i2 = deg2rad($dest_long);
85            
86 0           $d = acos(cos($l1 - $l2) - (1 - cos($i1 - $i2)) * cos($l1) * cos($l2));
87             # One degree of such an arc on the earth's surface is 60 international nautical miles NM
88 0           return rad2deg($d * 60);
89             }
90             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
91             #Calculates the direction from one point to another on the Earth
92             # a = arccos{[sin(lat2) - cos(d + lat1 - 1.5708)]/cos(lat1)/sin(d) + 1}
93             # Great Circle Bearing
94             sub GreatCircleDirection {
95 0     0 0   my ($self, $orig_lat, $dest_lat, $orig_long, $dest_long, $distance) = @_;
96 0           my ($a, $b, $d, $l1, $l2, $i1, $i2, $result, $dlong);
97            
98 0           $l1 = deg2rad($orig_lat);
99 0           $l2 = deg2rad($dest_lat);
100 0           $d = deg2rad($distance / 60); # divide by 60 for nautical miles NM to degree
101              
102 0           $i1 = deg2rad($orig_long);
103 0           $i2 = deg2rad($dest_long);
104 0           $dlong = $i1 - $i2;
105              
106 0           $a = sin($l2) - cos($d + $l1 - pi / 2);
107 0           $b = acos($a / (cos($l1) * sin($d)) + 1);
108 0 0 0       if ((abs($dlong) < pi && $dlong < 0) || (abs($dlong) > pi && $dlong > 0) ) {
      0        
      0        
109             #$b = (2 * pi) - $b;
110             }
111 0           $result = rad2deg($b);
112              
113 0           return $result;
114             }
115             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
116             #The Equivalent Earth redius is 6,378.14 Kilometers.
117             # Calculates the direction of the Qibla from any point on
118             # the Earth From North Clocklwise
119             sub QiblaDirection_ {
120 0     0 0   my ($self, $orig_lat, $orig_long) = @_;
121 0           my ($distance, $bearing);
122            
123             # Kabah Lat=21 Deg N, Long 40 Deg E
124 0           $distance = $self->GreatCircleDistance($orig_lat, $self->{DestLat}, $orig_long, $self->{DestLong});
125 0           $bearing = $self->GreatCircleDirection($orig_lat, $self->{DestLat}, $orig_long, $self->{DestLong}, $distance);
126              
127 0 0         if ($orig_lat > $self->{DestLat}) {
128             #$bearing += 180;
129             }
130              
131 0           return $bearing;
132             }
133             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
134             # Determine Qibla direction using basic spherical trigonometric formula
135             # Return float Qibla Direction from the north direction in degrees
136             sub QiblaDirection__ {
137            
138 0     0 0   my ($self, $orig_lat, $orig_long) = @_;
139              
140             #$orig_lat = 35.3833;
141             #$orig_long = 119.0166;
142             #Saudi Arabia, Riyadh Qibla = 245, Qibla Direction: 244.53 degees from true North, Distance from Ka'bah in Makkah: 790.18 km
143              
144 0           my $numerator = sin(deg2rad($self->{DestLong} - $orig_long));
145              
146 0           my $denominator = (cos(deg2rad($orig_lat)) * tan(deg2rad($self->{DestLat}))) -
147             (sin(deg2rad($orig_lat)) * cos(deg2rad($self->{DestLong} - $orig_long)));
148              
149 0           my $q = rad2deg(atan($numerator / $denominator));
150              
151 0 0         if ($orig_lat > $self->{DestLat}) {
152             #$q += 180;
153             }
154            
155             # Yemen, Sanaa = -35.57 from North = 324.43 from North
156 0 0         if ($q < 0) {
157             #$q += 360;
158             }
159 0           return $q;
160             }
161             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
162             # This is the only algorithm working with all other confirmed calculations
163             # See JS code source at http://www.moonsighting.com/qibla.html
164             sub QiblaDirection {
165            
166 0     0 0   my ($self, $lat, $lon) = @_;
167              
168             #$orig_lat = 35.3833;
169             #$orig_long = 119.0166;
170             #Saudi Arabia, Riyadh Qibla = 245, Qibla Direction: 244.53 degees from true North, Distance from Ka'bah in Makkah: 790.18 km
171              
172 0           my $latk = deg2rad($self->{DestLat});
173 0           my $longk = deg2rad($self->{DestLong});
174 0           my $phi = deg2rad($lat);
175 0           my $lambda = deg2rad($lon);
176 0           my $qiblad = rad2deg(atan2(sin($longk - $lambda), cos($phi)*tan($latk)-sin($phi)*cos($longk-$lambda)));
177 0 0         if ($qiblad < 0) {
178 0           $qiblad += 360;
179             }
180 0           return $qiblad;
181             }
182             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
183             =cuts
184             public function getQibla ()
185             {
186             // The geographical coordinates of the Ka'ba
187             $K_latitude = 21.423333;
188             $K_longitude = 39.823333;
189            
190             $latitude = $this->lat;
191             $longitude = $this->long;
192              
193             $numerator = sin(deg2rad($K_longitude - $longitude));
194             $denominator = (cos(deg2rad($latitude)) * tan(deg2rad($K_latitude))) -
195             (sin(deg2rad($latitude))
196             * cos(deg2rad($K_longitude - $longitude)));
197              
198             $q = atan($numerator / $denominator);
199             $q = rad2deg($q);
200            
201             if ($this->lat > 21.423333) {
202             $q += 180;
203             }
204            
205             return $q;
206             }
207              
208