* /trunk/src/gpstools/poisync
[gpstools.git] / branches / gpst.near / GPSTgeo.pm
blobf6b356917f5923791c5904a4c6f66fabfb23d606
1 package GPSTgeo;
3 #=======================================================================
4 # $Id$
6 # Character set: UTF-8
7 # ©opyleft 2002– Øyvind A. Holm <sunny@sunbase.org>
8 # License: GNU General Public License, see end of file for legal stuff.
9 #=======================================================================
11 use strict;
12 use warnings;
14 use GPSTdebug;
16 use Geo::Distance;
18 BEGIN {
19 use Exporter ();
20 our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
22 my $rcs_id = '$Id$';
23 push(@main::version_array, $rcs_id);
24 $VERSION = ($rcs_id =~ / (\d+) /, $1);
26 @ISA = qw(Exporter);
27 @EXPORT = qw(
28 $wpt_elems
29 &list_nearest_waypoints &ddd_to_dms &distance
31 %EXPORT_TAGS = ();
33 our @EXPORT_OK;
34 our $wpt_elems = "ele|time|magvar|geoidheight|name|cmt|desc|src|link|sym|" .
35 "type|fix|sat|hdop|vdop|pdop|ageofdgpsdata|dgpsid|" .
36 "extensions";
38 # FIXME: Hardcoding
39 my $waypoint_file = "$ENV{HOME}/bin/src/gpstools/tests/waypoints.gpx";
40 my @orig_waypoints = load_waypoints($waypoint_file);
42 sub list_nearest_waypoints {
43 # {{{
44 my ($Lat, $Lon, $Count) = @_;
45 my $Retval = "";
46 my @Waypoints = @orig_waypoints;
48 D("list_nearest_waypoints('$Lat', '$Lon', '$Count')");
50 for my $i (0 .. $#Waypoints) {
51 $Waypoints[$i]{'distance'} = distance(
52 $Lat, $Lon,
53 $Waypoints[$i]{'lat'},
54 $Waypoints[$i]{'lon'}
56 if ($main::Debug) {
57 my $dstr = "$i is { ";
58 for my $role (keys %{ $Waypoints[$i] }) {
59 $dstr .= "$role=\"$Waypoints[$i]{$role}\" ";
61 D($dstr . "}");
65 # my @Sorted = sort { $Waypoints[$b]{distance} } <=> $Waypoints[$a]{distance} } keys @Waypoints;
66 my @Sorted = sort_waypoints("distance", "+", \@Waypoints);
68 if ($main::Debug) {
69 for my $i (0 .. $#Waypoints) {
70 my $dstr = "sorted $i is { ";
71 for my $role (keys %{ $Sorted[$i] }) {
72 $dstr .= "$role=\"$Sorted[$i]{$role}\" ";
74 D($dstr . "}");
78 for my $i2 (0 .. $Count - 1) {
79 my $pos = $i2 + 1;
80 $Retval .= "<near pos=\"$pos\"> <name>$Sorted[$i2]{'name'}</name> <distance>$Sorted[$i2]{'distance'}</distance> </near>";
82 return($Retval);
83 # }}}
86 sub distance {
87 # Return distance between two positions. {{{
88 my ($Lat1, $Lon1, $Lat2, $Lon2, $Unit) = @_;
89 defined($Unit) || ($Unit = "metre");
90 my $Retval = "";
92 my $geo = new Geo::Distance;
93 $Retval = $geo->distance($Unit, $Lat1, $Lon1 => $Lat2, $Lon2);
94 return($Retval);
95 # }}}
98 sub load_waypoints {
99 # {{{
100 my $File = shift;
101 my @Retval = ();
103 D("Opening $File for read");
104 if (open(WaypFP, "<", $File)) {
105 my $Data = join("", <WaypFP>);
106 # D("Data = '$Data'");
107 close(WayFP);
108 @Retval = parse_waypoints($Data);
109 } else {
110 $main::Opt{'verbose'} && warn("$File: Cannot open file for read\n");
111 @Retval = undef;
113 D("load_waypoints('$File') returns '" . join("|", @Retval) . "'");
114 return @Retval;
115 # }}}
118 sub parse_waypoints {
119 # {{{
120 my $Data = shift;
121 my @Retval = ();
122 # D("parse_waypoints('$Data')");
123 $Data =~
125 <wpt\b(.*?)\blat="(.+?)".+?\blon="(.+?)".*?>(.*?)</wpt>
127 my ($Lat, $Lon, $el_wpt) =
128 (1.0 * $2, 1.0 * $3, $4);
129 my $wpt = {};
130 $wpt->{'lat'} = $Lat;
131 $wpt->{'lon'} = $Lon;
132 D("parse: Lat = '$Lat', Lon = '$Lon'");
133 $el_wpt =~
135 <($wpt_elems)\b.*?>(.*?)</($wpt_elems)>
137 my $Elem = $1;
138 $wpt->{$Elem} = $2;
140 }gsex;
141 push(@Retval, $wpt);
142 D("push Retval '$wpt'");
144 }gsex;
145 D("parse_waypoints() returns '" . join("|", @Retval) . "'");
146 return(@Retval);
147 # }}}
150 sub sort_waypoints {
151 # FIXME: Unfinished. {{{
152 my ($Key, $Dir) = (shift, shift);
153 my @Retval = @_;
154 return(@Retval);
155 # }}}
158 sub ddd_to_dms {
159 # Convert floating-point degrees into D°M'S.S" (ISO-8859-1).
160 # Necessary for import into GPSman. Based on toDMS() from
161 # gpstrans-0.39 to ensure compatibility.
162 # {{{
163 my $ddd = shift;
164 my $Neg = 0;
165 my ($Hour, $Min, $Sec) =
166 ( 0, 0, 0);
167 my $Retval = "";
169 ($ddd =~ /^\-?(\d*)(\.\d+)?$/) || return(undef);
170 length($ddd) || ($ddd = 0);
172 if ($ddd < 0.0) {
173 $ddd = 0 - $ddd;
174 $Neg = 1;
176 $Hour = int($ddd);
177 $ddd = ($ddd - $Hour) * 60.0;
178 $Min = int($ddd);
179 $Sec = ($ddd - $Min) * 60.0;
181 if ($Sec > 59.5) {
182 $Sec = 0.0;
183 $Min += 1.0;
185 if ($Min > 59.5) {
186 $Min = 0.0;
187 $Hour += 1.0;
189 $Retval = sprintf("%s%.0f\xB0%02.0f'%04.1f\"",
190 $Neg
191 ? "-"
192 : "",
193 $Hour, $Min, $Sec);
194 return $Retval;
195 # }}}