Subject: | bounds() does not work as documented, and TO_JSON support |
Thanks for a handy module!
One small gripe: $gpx->bounds() does not work as documented - it requires an $iterator
param. The attached patch fixes that by defaulting $iter to $self->iterate_points.
I'd also like to see TO_JSON support in the module so it can be serialized with JSON:: modules,
so I've implemented that too. The implementation could be more efficient by using Clone, but I
couldn't be bothered to add another dependency.
Both are tested.
Hope this helps,
-Steve
Subject: | Geo-Gpx-0.21-json-bounds.patch |
diff -ruN Geo-Gpx-0.21.orig/lib/Geo/Gpx.pm Geo-Gpx-0.21/lib/Geo/Gpx.pm
--- Geo-Gpx-0.21.orig/lib/Geo/Gpx.pm 2008-03-26 19:05:42.000000000 +0000
+++ Geo-Gpx-0.21/lib/Geo/Gpx.pm 2008-03-26 21:28:10.000000000 +0000
@@ -411,6 +411,7 @@
sub bounds {
my ( $self, $iter ) = @_;
+ $iter ||= $self->iterate_points;
my $bounds = {};
@@ -612,6 +613,20 @@
return join( '', @ret );
}
+# for JSON:: modules...
+sub TO_JSON {
+ my $self = shift;
+ my %json; #= map {$_ => $self->$_} ...
+ foreach my $key (@META, @ATTR) {
+ my $val = $self->$key;
+ $json{$key} = $val if defined( $val );
+ }
+ if (my $bounds = $self->bounds) {
+ $json{bounds} = $self->bounds;
+ }
+ return \%json;
+}
+
#### Legacy methods from 0.10
sub gpx {
@@ -689,7 +704,7 @@
been extended to support general parsing and generation of GPX data. GPX
1.0 and 1.1 are supported.
-=head1 INTERFACE
+=head1 INTERFACE
=over
@@ -705,24 +720,24 @@
New applications can use C<Geo::Gpx> to parse a GPX file:
my $gpx = Geo::Gpx->new( xml => $gpx_document );
-
+
or from an open filehandle:
my $gpx = Geo::Gpx->new( input => $fh );
-
+
or can create an empty container to which waypoints, routes and tracks can then be added:
my $gpx = Geo::Gpx->new();
$gpx->waypoints( \@wpt );
-=item C<bounds()>
+=item C<bounds( [ $iterator ] )>
Compute the bounding box of all the points in a C<Geo::Gpx> returning the result as a hash
reference. For example:
my $gpx = Geo::Gpx->new( xml => $some_xml );
my $bounds = $gpx->bounds();
-
+
returns a structure like this:
$bounds = {
@@ -732,12 +747,14 @@
maxlon => -1.230902
};
+C<$iterator> defaults to C<$self-E<gt>iterate_points>.
+
=item C<name( [ $newname ] )>
Accessor for the <name> element of a GPX. To get the name:
my $name = $gpx->name();
-
+
and to set it:
$gpx->name('My big adventure');
@@ -747,7 +764,7 @@
Accessor for the <desc> element of a GPX. To get the the description:
my $desc = $gpx->desc();
-
+
and to set it:
$gpx->desc('Got lost, wandered around for ages, got cold, got hungry.');
@@ -775,7 +792,7 @@
$gpx->author({
name => 'Me!'
});
-
+
The bizarre encoding of email addresses as id and domain is a feature of GPX.
=item C<time( [ $newtime ] )>
@@ -822,7 +839,7 @@
'text' => 'Hexten',
'href' => 'http://hexten.net/'
};
-
+
For example:
$gpx->link({ href => 'http://google.com/', text => 'Google' });
@@ -859,7 +876,7 @@
ageofdgpsdata => 45,
dgpsid => 247
};
-
+
All fields apart from C<lat> and C<lon> are optional. See the GPX
specification for an explanation of the fields. The waypoints array
is an anonymous array of such points:
@@ -1049,7 +1066,7 @@
my $gpx10 = $gpx->xml('1.0');
my $gpx11 = $gpx->xml('1.1');
-
+
If the version is omitted it defaults to the value of the C<version>
attibute. Parsing a GPX document sets the version. If the C<version>
attribute is unset defaults to 1.0.
@@ -1061,6 +1078,18 @@
C<Geo::Cache> points to the constructor; this should probably be avoided
for new applications.
+=item C<TO_JSON>
+
+For compatability with L<JSON> modules. Converts this object to a hash with
+keys that correspond to the above methods. Generated ala:
+
+ my %json = map {$_ => $self->$_}
+ qw(name desc author keywords copyright
+ time link waypoints tracks routes version );
+ $json{bounds} = $self->bounds( $iter );
+
+With one difference: the keys will only be set if they are defined.
+
=item C<gpx>
Synonym for C<xml()>. Provided for compatibility with version 0.10.
@@ -1107,7 +1136,7 @@
=head1 SEE ALSO
-L<Geo::Cache>
+L<Geo::Cache>, L<JSON>
=head1 BUGS AND LIMITATIONS
@@ -1152,3 +1181,5 @@
FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
+
+=cut
diff -ruN Geo-Gpx-0.21.orig/t/05.misc.t Geo-Gpx-0.21/t/05.misc.t
--- Geo-Gpx-0.21.orig/t/05.misc.t 2008-03-26 19:05:42.000000000 +0000
+++ Geo-Gpx-0.21/t/05.misc.t 2008-03-26 21:28:10.000000000 +0000
@@ -1,16 +1,17 @@
use strict;
use warnings;
-use Test::More tests => 5;
+use Test::More tests => 9;
use Geo::Gpx;
+my $time = time();
my @wpt = (
{
# All standard GPX fields
lat => 54.786989,
lon => -2.344214,
ele => 512,
- time => time(),
+ time => $time,
magvar => 0,
geoidheight => 0,
name => 'My house & home',
@@ -59,3 +60,46 @@
like $@, qr/mandatory in waypoint/, "mandatory lat, lon OK";
}
}
+
+{
+ my $gpx = Geo::Gpx->new;
+ $gpx->add_waypoint( @wpt );
+ my $iter = $gpx->iterate_points;
+ my $bounds = {
+ 'maxlat' => 54.786989,
+ 'maxlon' => -2.344214,
+ 'minlat' => -38.870059,
+ 'minlon' => -151.21003,
+ };
+ is_deeply $gpx->bounds, $bounds, "gpx->bounds doesn't require an iterator";
+}
+
+{
+ my $gpx = Geo::Gpx->new;
+ $gpx->add_waypoint( @wpt );
+ my $iter = $gpx->iterate_points;
+ my $expect = {
+ waypoints => \@wpt,
+ bounds => {
+ 'maxlat' => 54.786989,
+ 'maxlon' => -2.344214,
+ 'minlat' => -38.870059,
+ 'minlon' => -151.21003,
+ },
+ time => $time,
+ };
+ is_deeply $gpx->TO_JSON, $expect, "TO_JSON";
+ $gpx->name( 'spurkis' );
+ $expect->{name} = 'spurkis';
+ is_deeply $gpx->TO_JSON, $expect, "TO_JSON now has a name";
+
+ SKIP: {
+ eval "use JSON";
+ skip 'JSON not installed', 1 if $@;
+
+ my $coder = JSON->new->allow_blessed->convert_blessed;
+ my $json = $coder->encode( $gpx );
+ my $json2 = $coder->encode( $expect );
+ is_deeply $json, $json2, "works with JSON module";
+ };
+}