Geo-Point-0.96/0000755000175000001440000000000012267473551014003 5ustar00markovusers00000000000000Geo-Point-0.96/META.yml0000644000175000001440000000103712267473551015255 0ustar00markovusers00000000000000--- abstract: 'Geographical structures' author: - 'Mark Overmeer' build_requires: ExtUtils::MakeMaker: 0 configure_requires: ExtUtils::MakeMaker: 0 dynamic_config: 1 generated_by: 'ExtUtils::MakeMaker version 6.64, CPAN::Meta::Converter version 2.120630' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: Geo-Point no_index: directory: - t - inc requires: Geo::Distance: 0.06 Geo::Proj4: 1.01 Math::Polygon: 1.01 Math::Trig: 1 Test::More: 0.47 version: 0.96 Geo-Point-0.96/Makefile.PL0000644000175000001440000000210412267431704015744 0ustar00markovusers00000000000000use ExtUtils::MakeMaker; require 5.008; WriteMakefile ( NAME => 'Geo::Point' , VERSION => '0.96' , PREREQ_PM => { Test::More => 0.47 , Geo::Distance => 0.06 , Geo::Proj4 => 1.01 , Math::Polygon => 1.01 , Math::Trig => 1.00 } , AUTHOR => 'Mark Overmeer' , ABSTRACT => 'Geographical structures' , LICENSE => 'perl' ); #### the next lines are added for OODoc, which generates the #### distribution. sub MY::postamble { <<'__POSTAMBLE' } # for DIST RAWDIR = ../public_html/geopoint/raw DISTDIR = ../public_html/geopoint/source LICENSE = artistic # for POD FIRST_YEAR = 2005 EMAIL = perl@overmeer.net WEBSITE = http://perl.overmeer.net/geo/ # for HTML EXTENDS = ../MathPolygon:../GeoProj4:../GeoWKT:../GeoGML:../Geo139:../GeoEOP:../XMLCompile:../XMLCache:../Envisat:../Landsat:../DBD-mysql-Geom HTML_OUTPUT = ../public_html/geo/html HTML_DOCROOT = /geo/html HTML_PACKAGE = ../public_html/geo/htmlpkg PODTAIL = ../Geo-shared-podtail __POSTAMBLE Geo-Point-0.96/README0000644000175000001440000000050412267243164014655 0ustar00markovusers00000000000000 Geo::Point =========== Geo::Point tries to abstract coordinate systems. It does not try to solve all the problems itself, but will call-out for helper modules when computation has to be done. The module is heavily resting on Math::Polygon. Improvements and additions please to Mark Overmeer, Geo-Point-0.96/ChangeLog0000644000175000001440000000653012267473543015562 0ustar00markovusers00000000000000Revision history for Perl extension Geo::Point version 0.96: Tue Jan 21 14:34:23 CET 2014 Improvements: - more work on docs. version 0.95: Mon Jan 20 16:54:57 CET 2014 Fixes: - typos. rt.cpan.org#82902 [Xavier Guimard] - Geo::Distance integration rt.cpan.org#92242 [Niko Tyni], http://bugs.debian.org/735744 Improvements: - change documentation style. version 0.94: Fri Dec 21 12:19:47 CET 2012 Fixes: - fix ::Surface::bbox() version 0.93: Wed May 19 23:31:05 CEST 2010 Fixes: - ::Surface::geo_outer() and geo_inner() renamed to ::geoOuter() and ::geoInner(), to be consequent with naming convensions. Older names still supported but not documented anymore. - Geo::Proj::zoneForUTM() used 'zone' as proj4 option, where it should be '+zone'. [Michael R. Davis] - Geo::Proj:zoneForUTM() miscalculated zones with negative longitudes. [Michael R. Davis] version 0.92: Thu Dec 24 12:08:04 CET 2009 Fixes: - synopsis mistakes in Geo::Proj, spotted by rt.cpan.org#47953 [Don Reid] version 0.91: Mon May 25 14:31:47 CEST 2009 Fixes: - the Geo::Surface was very seriously broken. version 0.90: Tue Jan 27 16:45:11 CET 2009 Fixes: - do not use /bin/pwd in t/pod.t - detected projection of ::Surface not registered. version 0.10: Wed Jan 21 10:04:19 CET 2009 Fixes: - projection lost during line creation from geopoints. - default projection must be expressed as label, not object. - default projection for surface is that of first component. - many fixes to Surface initiation. version 0.09: Fri Jan 2 20:08:35 CET 2009 Fixes: - creation of Geo::Line objects based on Geo::Point objects. rt.cpan.org#42076 [Jonathan Yu] - fix call to bestUTMprojection for 'utm' default nick-name - repare UTM zone calculation. - repare reprojecting of lines. Improvement: - croak when object is passed as proj parameter: must be a Geo::Proj label. version 0.08: Mon Mar 31 08:58:30 CEST 2008 - very stupid bugs when 0 was used as lat or long. Hit by [Paul Tomblin] version 0.07: Tue Feb 12 10:00:05 CET 2008 - use Geo::Distance for Geo::Shape::distance [Mark Lawrence] - use Math::Trig for Geo::Shape::distance [Mark Lawrence] - added dependency for Math::Trig - add '0' before 1 digit minutes and seconds in deg2dm() and deg2dms() - GeoPoint is stable for quite some time, but the man-page still contained ALPHA and BETA release warnings. - added toString() as prefered over string(). version 0.06: Mon Jun 11 16:55:01 CEST 2007 - added t/pod.t version 0.05: Fri Mar 9 14:18:25 CET 2007 - Converted to use oodist, removing mkdist, mkdoc, version. - removed superfluous html/index.html - email address now geo@, webpage /geo/ - all error messages should start with lower-case version 0.04: Thu Nov 30 15:08:19 CET 2006 - Removed some (harmless) debugging traps - Geo::Point::normalize() version 0.03: Mon Oct 9 20:04:16 CEST 2006 - Do not keep Geo::Proj4 object within Geo::Shape, so Geo objects can be used in a database. - Newest OODoc produces better man-pages. version 0.002: Mon Sep 25 16:01:18 CEST 2006 - fix of Geo::Proj::default projection(): should always return a nickname, not an object. - overloading with enabled fallback, which fixes some test problems. by [Chia-liang Kao]. - overload cmp in Geo::Proj version 0.001: Mon Dec 12 12:04:21 CET 2005 Initial release Geo-Point-0.96/lib/0000755000175000001440000000000012267473551014551 5ustar00markovusers00000000000000Geo-Point-0.96/lib/Geo/0000755000175000001440000000000012267473551015263 5ustar00markovusers00000000000000Geo-Point-0.96/lib/Geo/Proj.pod0000644000175000001440000001543212267473546016712 0ustar00markovusers00000000000000=encoding utf8 =head1 NAME Geo::Proj - Handling projections =head1 SYNOPSIS use Geo::Proj; my $wgs84 = Geo::Proj->new # predefined if import() ( nick => 'wgs84' , proj4 => '+proj=latlong +datum=WGS84 +ellps=WGS84' ); my $clrk = Geo::Proj->new ( nick => 'clark66' , proj4 => [proj => "merc", ellps => "clrk66", lon_0 => -96] ); my $point_wgs84= Geo::Point->latlong(56.12, 4.40, 'wgs84'); my $point_wgs84= Geo::Point->latlong(56.12, 4.40, $wgs84); my $point_clrk = $point_wgs84->in($clrk); my $point_clrk = Geo::Proj->to($wgs84, $clrk, $point_wgs84); my $point_clrk = Geo::Proj->to($wgs84, 'clark66', $point_wgs84); =head1 DESCRIPTION A point on Earth's surface can be represented in many different coordinate systems. The L module wraps the popular Open Source C library to convert between those coordinate systems; a very complex job. Within a program, however, you like some extra abstraction from that library: to be able to simply label a point to its system, and then forget about all transformations which may be necessary. The label (or C) hides all complicated parameters for the actual projection . WARNING 1: this class will collect all nicks, which means that calling L with the same label twice will have the second ignored. WARNING 2: the wgs84 nickname is predefined, but only if this module is 'used' with import. So if you decide to use 'require' to dynamically load this module, then don't forget to call 'import()' yourself, or define the wgs84 projection yourself. =head1 METHODS =head2 Constructors =over 4 =item Geo::Proj-EB([$nick], %options) Create a new object. -Option--Default name nick proj4 srid undef =over 2 =item name => STRING =item nick => LABEL The abbrevated name for this projection. =item proj4 => OBJECT|ARRAY|STRING The ARRAY or STRING will by used to create a L object by calling L. You may also specify such an prepared OBJECT. =item srid => INTEGER SRID stands for "Spatial Reference System ID", which is just an index in a table of spatial descriptions as used by SQL. Only INTEGER values larger than 0 are permitted. =back =back =head2 Attributes =over 4 =item $obj-EB() The full, official name of the projection =item $obj-EB() Simple abbreviating of the projection. =item $obj-EB([ <$nick|$proj4> ]) =item Geo::Proj-EB([ <$nick|$proj4> ]) Returns the projection library handle (a L) to be used by this component. As class method, the $nick is specified for a lookup. In case a $proj4 is specified, that is returned. example: my $wgs84 = Geo::Proj->new(nick => 'wgs84', ...); my $wgs84_proj4 = Geo::Proj->proj4('wgs84'); my $wgs84_proj4 = Geo::Proj->proj4($wgs84); my $wgs84_proj4 = $wgs84->proj4; =item $obj-EB() The "Spatial Reference System ID" if known. =back =head2 Projecting =over 4 =item Geo::Proj-EB([ <$nick|$proj> ]) The $nick must be defined with L. Returned is the Geo::Proj object for the default projection. The default is the first name created, which probably is 'wgs84' (when import() had a chance) =item Geo::Proj-EB([$fh]) Print details about the defined projections to the $fh, which defaults to the selected. Especially useful for debugging. =item Geo::Proj-EB() Returns a sorted lost of projection nicks. =item Geo::Proj-EB(<$nick|$proj>) Returns the L object, defined with $nick. In case such an object is passed in as $proj, it is returned unaffected. This method is used where in other methods NICKS or $proj can be used as arguments. example: my $wgs84 = Geo::Proj->projection('wgs84'); my $again = Geo::Proj->projection($wgs84); =item $obj-EB([<$proj|$nick>], <$proj|$nick>, $point|ARRAY-of-$points) =item Geo::Proj-EB([<$proj|$nick>], <$proj|$nick>, $point|ARRAY-of-$points) Expects an Geo::Proj to project the $point or $points to. The work is done by L. As class method, you have to specify two nicks or projections. Be warned that this L method expects POINTs which are B L objects, but which themselves are an ARRAY containing X,Y and optionally a Z coordinate. example: my $p2 = $wgs84->to('utm31-wgs84', $p1); my $p2 = $wgs84->to($utm, $p1); my $p2 = Geo::Proj->to('wgs84', 'utm31-wgs84', $p1); =back =head2 UTM =over 4 =item Geo::Proj-EB(<$datum|$proj|undef>, $zone) The $proj is a L which is used to collect the datum information from if no $datum was specified explicitly. It may also be a string which is the name of a datum, as known by proj4. Undef will be replaced by the default projection. example: my $proj = Geo::Proj->UTMprojection('WGS84', 31) or die; print $proj->nick; # for instance utm31-wgs84 =item $obj-EB($point, [$proj|$nick]) =item Geo::Proj-EB($point, [$proj|$nick]) Returns the best UTM projection for some $point. As class method, you specify the nickname or the object for the point. example: my $point = Geo::Point->longlat(2.234, 52.12); my $proj = Geo::Proj->bestUTMprojection($point); print $proj->nick; # for instance utm31-wgs84 =item $obj-EB($point) =item Geo::Proj-EB($point) Provided some point, figure-out which zone is most optimal for representing the point. In LIST context, zone number, zone letter, and meridian are returned as separate scalars. In LIST context, the zone number and letter are returned as one.. This code is stolen from L, because that module immediately starts to do computations with this knowledge, which is not wanted here. Probably a lot of zones are missing. =back =head1 OVERLOADING =over 4 =item overload: B<'""' (stringification)> Returns the nick-name for this projection. =back =head1 SEE ALSO This module is part of Geo-Point distribution version 0.96, built on January 21, 2014. Website: F All modules in this suite: L, L, L, L, L, L, L, L, and L. Please post questions or ideas to the mailinglist at F =head1 LICENSE Copyrights 2005-2014 by [Mark Overmeer]. For other contributors see ChangeLog. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See F Geo-Point-0.96/lib/Geo/Point.pm0000644000175000001440000002011512267473543016712 0ustar00markovusers00000000000000# Copyrights 2005-2014 by [Mark Overmeer]. # For other contributors see ChangeLog. # See the manual pages for details on the licensing terms. # Pod stripped from pm file by OODoc 2.01. use strict; use warnings; package Geo::Point; use vars '$VERSION'; $VERSION = '0.96'; use base 'Geo::Shape'; use Geo::Proj; use Carp qw/confess croak/; sub init($) { my ($self, $args) = @_; $self->SUPER::init($args); $self->{GP_x} = defined $args->{x} ? $args->{x} : defined $args->{long} ? $args->{long} : $args->{longitude}; $self->{GP_y} = defined $args->{y} ? $args->{y} : defined $args->{lat} ? $args->{lat} : $args->{latitude}; $self; } sub latlong(@) { my $thing = shift; if(ref $thing) # instance method { return ($thing->{GP_y}, $thing->{GP_x}) unless @_ > 2; my $proj = pop @_; return $thing->in($proj)->latlong; } # class method $thing->new(lat => shift, long => shift, proj => shift); } sub longlat(@) { my $thing = shift; if(ref $thing) # instance method { return ($thing->{GP_x}, $thing->{GP_y}) unless @_ > 2; my $proj = pop @_; return $thing->in($proj)->longlat; } # class method $thing->new(long => shift, lat => shift, proj => shift); } sub xy(@) { my $thing = shift; if(ref $thing) # instance method { return ($thing->{GP_x}, $thing->{GP_y}) unless @_ > 2; my $proj = pop @_; return $thing->in($proj)->xy; } # class method $thing->new(x => shift, y => shift, proj => shift); } sub yx(@) { my $thing = shift; if(ref $thing) # instance method { return ($thing->{GP_y}, $thing->{GP_x}) unless @_ > 2; my $proj = pop @_; return $thing->in($proj)->yx; } # class method $thing->new(y => shift, x => shift, proj => shift); } sub fromString($;$) { my ($class, $string, $nick) = @_; defined $string or return; $string =~ s/^\s+//; $string =~ s/\s+$//; return () unless length $string; # line starts with project label $nick = $1 if $string =~ s/^(\w+)\s*\:\s*//; # The line is either split by comma's or by blanks. my @parts = $string =~ m/\,/ ? (split /\s*\,\s*/, $string) : (split /\s+/, $string); # Now, the first word may be a projection. That is: any non-coordinate, # anything which starts with more than one letter. if($parts[0] =~ m/^[a-z_]{2}/i) { $nick = shift @parts; # overrules default } my $proj; if(!defined $nick) { $proj = Geo::Proj->defaultProjection; $nick = $proj->nick; } elsif($nick eq 'utm') { die "ERROR: UTM requires 3 values: easting, northing, and zone\n" unless @parts==3; my $zone; if($parts[0] =~ m/^\d\d?[C-HJ-NP-X]?$/i ) { $zone = shift @parts; } elsif($parts[2] =~ m/^\d\d?[C-HJ-NP-X]?$/i ) { $zone = pop @parts; } if(!defined $zone || $zone==0 || $zone > 60) { die "ERROR: illegal UTM zone in $string"; } $proj = Geo::Proj->UTMprojection(undef, $zone); $nick = $proj->nick; } else { $proj = Geo::Proj->projection($nick) or croak "ERROR: undefined projection $nick"; } croak "ERROR: too few values in '$string' (got ".@parts.", expect 2)\n" if @parts < 2; croak "ERROR: too many values in '$string' (got ".@parts.", expect 2)\n" if @parts > 2; if($proj->proj4->isLatlong) { my ($lats, $longs) = ( $parts[0] =~ m/[ewEW]$/ || $parts[1] =~ m/[nsNS]$/ || $parts[0] =~ m/^[ewEW]/ || $parts[1] =~ m/^[nsNS]/ ) ? reverse(@parts) : @parts; my $lat = $class->dms2deg($lats); defined $lat or die "ERROR: dms latitude coordinate not understood: $lats\n"; my $long = $class->dms2deg($longs); defined $long or die "ERROR: dms longitude coordinate not understood: $longs\n"; return $class->new(lat => $lat, long => $long, proj => $nick); } else # type eq xy { my ($x, $y) = @parts; die "ERROR: illegal character in x coordinate $x" unless $x =~ m/^\d+(?:\.\d+)$/; die "ERROR: illegal character in y coordinate $y" unless $y =~ m/^\d+(?:\.\d+)$/; return $class->new(x => $x, y => $y, proj => $nick); } (); } #---------------- sub longitude() {shift->{GP_x}} sub long() {shift->{GP_x}} sub latitude() {shift->{GP_y}} sub lat() {shift->{GP_y}} sub x() {shift->{GP_x}} sub y() {shift->{GP_y}} #---------------- sub in($) { my ($self, $newproj) = @_; # Dirty hacks violate OO, to improve the speed. return $self if $newproj eq $self->{G_proj}; my ($n, $p) = $self->projectOn($newproj, [$self->{GP_x}, $self->{GP_y}]); $p ? ref($self)->new(x => $p->[0], y => $p->[1], proj => $n) : $self; } sub normalize() { my $self = shift; my $p = Geo::Proj->projection($self->proj); $p && $p->proj4->isLatlong or return $self; my ($x, $y) = @$self{'GP_x','GP_y'}; $x += 360 while $x < -180; $x -= 360 while $x > 180; $y += 180 while $y < -90; $y -= 180 while $y > 90; @$self{'GP_x','GP_y'} = ($x, $y); $self; } #---------------- sub bbox() { @{(shift)}[ qw/GP_x GP_y GP_x GP_y/ ] } sub area() { 0 } sub perimeter() { 0 } # When two points are within one UTM zone, this could be done much # easier... sub distancePointPoint($$$) { my ($self, $geodist, $units, $other) = @_; my $here = $self->in('wgs84'); my $there = $other->in('wgs84'); $geodist->distance($units, $here->latlong, $there->latlong); } sub sameAs($$) { my ($self, $other, $e) = (shift, shift); croak "ERROR: can only compare a point to another Geo::Point" unless $other->isa('Geo::Point'); # may be latlong or xy, doesn't matter: $e is corrected for that my($x1, $y1) = $self->xy; my($x2, $y2) = $other->xy; abs($x1-$x2) < $e && abs($y1-$y2) < $e; } sub inBBox($) { my ($self, $other) = @_; my ($x, $y) = $self->in($other->proj)->xy; my ($xmin, $ymin, $xmax, $ymax) = $other->bbox; $xmin <= $x && $x <= $xmax && $ymin <= $y && $y <= $ymax } #---------------- sub coordsUsualOrder() { my $self = shift; my $p = Geo::Proj->projection($self->proj); $p && $p->proj4->isLatlong ? $self->latlong : $self->xy; } sub coords() { my ($a, $b) = shift->coordsUsualOrder; defined $a && defined $b or return '(none)'; sprintf "%.4f %.4f", $a, $b; } sub toString(;$) { my ($self, $proj) = @_; my $point; if(defined $proj) { $point = $self->in($proj); } else { $proj = $self->proj; $point = $self; } "point[$proj](" .$point->coords.')'; } *string = \&toString; sub dms(;$) { my ($self, $proj) = @_; my ($long, $lat) = $proj ? $self->in($proj)->longlat : $self->longlat; my $dmslat = $self->deg2dms($lat, 'N', 'S'); my $dmslong = $self->deg2dms($long, 'E', 'W'); wantarray ? ($dmslat, $dmslong) : "$dmslat, $dmslong"; } sub dm(;$) { my ($self, $proj) = @_; my ($long, $lat) = $proj ? $self->in($proj)->longlat : $self->longlat; my $dmlat = $self->deg2dm($lat, 'N', 'S'); my $dmlong = $self->deg2dm($long, 'E', 'W'); wantarray ? ($dmlat, $dmlong) : "$dmlat, $dmlong"; } sub dmsHTML(;$) { my ($self, $proj) = @_; my @both = $self->dms($proj); foreach (@both) { s/"/\"/g; # The following two translations are nice, but IE does not handle # them correctly when uses as values in form fields. # s/d/\°/g; # s/ /\ \ /g; } wantarray ? @both : "$both[0], $both[1]"; } sub dmHTML(;$) { my ($self, $proj) = @_; my @both = $self->dm($proj); foreach (@both) { s/"/\"/g; # See dmsHTML above # s/d/\°/g; # s/ /\ \ /g; } wantarray ? @both : "$both[0], $both[1]"; } sub moveWest() { my $self = shift; $self->{GP_x} -= 360 if $self->{GP_x} > 0; } 1; Geo-Point-0.96/lib/Geo/Point.pod0000644000175000001440000002717012267473546017073 0ustar00markovusers00000000000000=encoding utf8 =head1 NAME Geo::Point - a point on the globe =head1 INHERITANCE Geo::Point is a Geo::Shape =head1 SYNOPSIS use Geo::Point; my $p = Geo::Point->latlong(1,2); my $p = Geo::Point->longlat(2,1); my $w = Geo::Proj->new(wgs84 => ...); my $p = Geo::Point->latlong(1,2, 'wgs84'); my ($lat, $long) = $p->latlong; my ($x, $y) = $p->xy; my ($x, $y) = $p->in('utm31-wgs84'); my $p = Geo::Point->xy(1,2); =head1 DESCRIPTION One location on the globe, in any coordinate system. This package tries to hide the maths and the coordinate system in which the point is represented. One of the most confusing things when handling geometrical data, is that sometimes latlong, sometimes xy are used: horizontal and vertical organization reversed. This package tries to hide this from your program by providing abstract accessors L, L, L, and L. Extends L<"DESCRIPTION" in Geo::Shape|Geo::Shape/"DESCRIPTION">. =head1 METHODS Extends L<"METHODS" in Geo::Shape|Geo::Shape/"METHODS">. =head2 Constructors Extends L<"Constructors" in Geo::Shape|Geo::Shape/"Constructors">. =over 4 =item Geo::Point-EB($string, [$projection]) Create a new point from a $string. The coordinates can be separated by a comma (preferrably), or blanks. When the coordinates end on NSEW, the order does not matter, otherwise lat-long or xy order is presumed. This routine is very smart. It understands: PROJLABEL VALUE VALUE PROJLABEL: VALUE VALUE PROJLABEL, VALUE, VALUE PROJLABEL: VALUE, VALUE VALUE VALUE VALUE, VALUE utm: ZONE, VALUE, VALUE # also without commas and ':' utm: VALUE, VALUE, ZONE # also without commas and ':' utm: VALUE, VALUE # also without commas and ':' ZONE, VALUE, VALUE # also without commas and ':' VALUE, VALUE, ZONE # also without commas and ':' The VALUE must be suitable for projection. If only two values are provided, a C, single or double quote, or trailing/leading C, C, C, C (either lower or upper-case) will force a latlong projection. Those coordinates must follow the rules of L. example: point from string my $x = 'utm 31n 12311.123 34242.12'; # utm zone 31N my $x = '12311.123 34242.12 31'; # utm zone 31 my $x = '123.123E 12.34'; # wgs84 latlong my $x = 'clrk66 123.123 12.34'; # clrk66 latlong my $x = '12d34'123.1W 11.1123'; # wgs84 longlat my $p = Geo::Point->fromString($x); # When parsing user applications, you probably want: my $p = eval { Geo::Point->fromString($x) }; warn $@ if $@; =item $obj-EB([ $lat,$long,[$proj] ] | [$proj]) =item Geo::Point-EB([ $lat,$long,[$proj] ] | [$proj]) When called as class method, you create a new point. Provide a LATitude and LONGitude. The optional PROJection tells in which coordinate system. As instance method, the latitude and longitude are reported. You can ask it to be translated into the $proj coordinate system first. When $proj is undefined, none is presumed. The project must be specified as string, which referse to a projection defined by L. See also L, L, and L. example: latlong as class method my $wgs84 = Geo::Proj->new(wgs84 => ...); my $gp = Geo::Point->latlong(52.3213, 5.53, 'wgs84'); example: latlong as instance method my ($lat, $long) = $gp->latlong('wgs84'); =item $obj-EB([ $long,$lat,[$proj] ] | [$proj]) =item Geo::Point-EB([ $long,$lat,[$proj] ] | [$proj]) Like L, but with the coordinates reversed. Some applications prefer this. =item Geo::Point-EB(%options) -Option --Defined in --Default lat undef latitude undef long undef longitude undef proj Geo::Shape see Geo::Proj::defaultProjection() x undef y undef =over 2 =item lat => COORDINATE =item latitude => COORDINATE =item long => COORDINATE =item longitude => COORDINATE =item proj => LABEL =item x => COORDINATE =item y => COORDINATE =back =item $obj-EB([$x, $y, [$proj] ] | [$proj]) =item Geo::Point-EB([$x, $y, [$proj] ] | [$proj]) Like L but now for carthesian projections. Usually, the coordinate order is reversed. See also L. =item $obj-EB([$y, $x, [$proj] ] | [$proj]) =item Geo::Point-EB([$y, $x, [$proj] ] | [$proj]) Like L but now for carthesian projections. Usually, the coordinate order is reversed. See also L. =back =head2 Attributes Extends L<"Attributes" in Geo::Shape|Geo::Shape/"Attributes">. =over 4 =item $obj-EB() Inherited, see L =item $obj-EB() Inherited, see L =back =head2 Accessors The accessors only work correctly when you are sure that the point is in the right coordinate systems. =over 4 =item $obj-EB() =item $obj-EB() =item $obj-EB() =item $obj-EB() =item $obj-EB() =item $obj-EB() =back =head2 Projections Extends L<"Projections" in Geo::Shape|Geo::Shape/"Projections">. =over 4 =item $obj-EB(<$label|'utm'>) Inherited, see L =item $obj-EB() Be sure the that coordinates are between -180/180 longitude, -90/90 lattitude. No changes for non-latlong projections. =item $obj-EB($nick, @points) Inherited, see L =back =head2 Geometry Extends L<"Geometry" in Geo::Shape|Geo::Shape/"Geometry">. =over 4 =item $obj-EB() Always returns zero. =item $obj-EB() The bounding box of a point contains twice itself. =item $obj-EB() Inherited, see L =item $obj-EB([$xmin, $ymin, $xmax, $ymax, [$proj]]) =item Geo::Point-EB([$xmin, $ymin, $xmax, $ymax, [$proj]]) Inherited, see L =item $obj-EB($object, [$unit]) Inherited, see L =item $obj-EB($geodist, $units, $point) Compute the distance between the current point and some other $point in $units. The $geodist object will do the calculations. See L. =item $obj-EB($object) Returns a true value if this point is inside the bounding box of the specified $object. The borders of the bbox are included. This is relatively fast to check, even for complex objects. When the projections differ, the point is translated into the $object's coordinate system, because that one must stay square. =item $obj-EB() Always returns zero. =item $obj-EB($other, $tolerance) =back =head2 Display Extends L<"Display" in Geo::Shape|Geo::Shape/"Display">. =over 4 =item $obj-EB() Returns the coordinates in their usual order, formatted as string with a joining blank; =item $obj-EB() Returns the coordinates in the order which is usual for the projection used. =item $obj-EB($degrees, $pos, $neg) =item Geo::Point-EB($degrees, $pos, $neg) Inherited, see L =item $obj-EB($degrees, $pos, $neg) =item Geo::Point-EB($degrees, $pos, $neg) Inherited, see L =item $obj-EB([$projection]) Like L, but doesn't show seconds. =item $obj-EB([$projection]) Like L, but does not show seconds. =item $obj-EB([$projection]) Show the point as DMS value-pair. You must be sure that the coordinate is a projection for which is it useful to represent the values in DMS. In SCALAR context, one string is returned. In LIST context, the values are returned separately in latlong order. Be warned, that the returned string may contain single and double quote characters, which may confuse HTML (see L). =item $obj-EB($dms) =item Geo::Point-EB($dms) Inherited, see L =item $obj-EB([$projection]) Like L, but all character which are troublesome for HTML are translated into character codes. =item $obj-EB() Move a point from the eastern calculations into the western calculations, resulting in a value below -180. This is useful when this point is part of a larger construct, like the corners of a satellite image, which are both sides of the -180 meridian. example: moving West my $point = Geo::Point->latlong(24, 179); $point->moveWest; print $point->long; # -181; =item $obj-EB([$projection]) Returns a string representation of the point, which is also used for stringification. The default projection is the one of the point. example: print "Point: ",$gp->toString, "\n"; print "Point: $gp\n"; # same print "Point: ",$gp->toString('clrk66'), "\n"; =back =head1 OVERLOAD Extends L<"OVERLOAD" in Geo::Shape|Geo::Shape/"OVERLOAD">. =over 4 =item overload: B<'""' (stringification)> Inherited, see L =item overload: B<'bool' (truth value)> Inherited, see L =back =head1 DIAGNOSTICS =over 4 =item Error: UTM requires 3 values: easting, northing, and zone =item Error: can only compare a point to another Geo::Point =item Error: distance calculation not implemented between a $kind and a $kind Only a subset of all objects can be used in the distance calculation. The limitation is purely caused by lack of time to implement this. =item Error: dms latitude coordinate not understood: $string See L for permitted formats. =item Error: dms longitude coordinate not understood: $string See L for permitted formats. =item Error: illegal UTM zone in $string A UTM zone can be detected at the beginning or at the end of the input. It contains a number (from 1 upto 60) and an optional latitude indication (C upto X, except I and O). =item Error: illegal character in x coordinate $x =item Error: illegal character in y coordinate $y =item Error: in() not implemented for a $class =item Error: too few values in $string (got @parts) Most projection require two parameters, but utm requires three (with zone). =item Error: too many values in $string (got @parts) Most projection require two parameters, but utm requires three (with zone). =item Error: undefined projection $proj for $string The projection you used (or is set as default) is not defined. See L about how to defined them. =back =head1 SEE ALSO This module is part of Geo-Point distribution version 0.96, built on January 21, 2014. Website: F All modules in this suite: L, L, L, L, L, L, L, L, and L. Please post questions or ideas to the mailinglist at F =head1 LICENSE Copyrights 2005-2014 by [Mark Overmeer]. For other contributors see ChangeLog. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See F Geo-Point-0.96/lib/Geo/Space.pm0000644000175000001440000000446412267473543016665 0ustar00markovusers00000000000000# Copyrights 2005-2014 by [Mark Overmeer]. # For other contributors see ChangeLog. # See the manual pages for details on the licensing terms. # Pod stripped from pm file by OODoc 2.01. use strict; use warnings; package Geo::Space; use vars '$VERSION'; $VERSION = '0.96'; use base 'Geo::Shape'; use Math::Polygon::Calc qw/polygon_bbox/; use List::Util qw/sum first/; sub new(@) { my $thing = shift; my @components; push @components, shift while ref $_[0]; my %args = @_; if(ref $thing) # instance method { $args{proj} ||= $thing->proj; } my $proj = $args{proj}; return () unless @components; $thing->SUPER::new(components => \@components); } sub init($) { my ($self, $args) = @_; $self->SUPER::init($args); $self->{GS_comp} = $args->{components} || []; $self; } sub components() { @{shift->{GS_comp}} } sub component(@) { my $self = shift; wantarray ? $self->{GS_comp}[shift] : @{$self->{GS_comp}}[@_]; } sub nrComponents() { scalar @{shift->{GS_comp}} } sub points() { grep $_->isa('Geo::Points'), shift->components } sub onlyPoints() { not first {! $_->isa('Geo::Points')} shift->components } sub lines() { grep $_->isa('Geo::Line'), shift->components } sub onlyLines() { not first {! $_->isa('Geo::Line')} shift->components } sub onlyRings() { not first {! $_->isa('Geo::Line') || ! $_->isRing} shift->components } sub in($) { my ($self, $projnew) = @_; return $self if ! defined $projnew || $projnew eq $self->proj; my @t; foreach my $component ($self->components) { ($projnew, my $t) = $component->in($projnew); push @t, $t; } (ref $self)->new(@t, proj => $projnew); } sub bbox() { my $self = shift; my @bboxes = map [$_->bbox], $self->components; polygon_bbox(map +([$_->[0], $_->[1]], [$_->[2], $_->[3]]), @bboxes); } sub area() { sum map $_->area, shift->components } sub perimeter() { sum map $_->perimeter, shift->components } sub toString(;$) { my ($self, $proj) = @_; my $space; if(defined $proj) { $space = $self->in($proj); } else { $proj = $self->proj; $space = $self; } "space[$proj]\n (" . join(")\n (", map {$_->string} $space->components) . ")\n"; } *string = \&toString; 1; Geo-Point-0.96/lib/Geo/Shape.pod0000644000175000001440000001336112267473546017037 0ustar00markovusers00000000000000=encoding utf8 =head1 NAME Geo::Shape - base class for 2-dimensional points on the earth surface =head1 INHERITANCE Geo::Shape is extended by Geo::Line Geo::Point Geo::Space Geo::Surface =head1 SYNOPSIS use Geo::Shape; my $p1 = Geo::Point->new(lat => 2.17, ...); my $p2 = Geo::Point->latlong(2.17, 3.14); # wgs84 is default my $p3 = $p1->in('wgs84'); # conversion my $p4 = $p1->in('utm'); # conversion =head1 DESCRIPTION Base class for the many geo-spatial objects defined by the GeoPoint distribution. =head1 METHODS =head2 Constructors =over 4 =item Geo::Shape-EB(%options) Create a new object. -Option--Default proj see Geo::Proj::defaultProjection() =over 2 =item proj => LABEL =back =back =head2 Attributes =over 4 =item $obj-EB() Returns the nickname of the projection used by the component. B this is not a L object, but just a label. =item $obj-EB() Returns the proj4 object which handles the projection. =back =head2 Projections =over 4 =item $obj-EB(<$label|'utm'>) The coordinates of this point in a certain projection, refered to with the $label. The projection is defined with L. When simply 'utm' is provided, the best UTM zone is selected. In LIST context, the coordinates are returned. In SCALAR context, a new object is returned. example: my $gp = Geo::Point->latlong(1,2); # implicit conversion to wgs84, if not already in latlong my ($lat, $long) = $pr->latlong; # will select an utm zone for you my $p_utm = $gp->in('utm'); my ($x, $y) = $p_utm->xy; my $label = $p_utm->proj; my ($datum, $zone) = $label =~ m/^utm-(\w+)-(\d+)$/; =item $obj-EB($nick, @points) The @points are ARRAYs with each an X and Y coordinate of a single point in space. A list of transformed points is returned, which is empty if no change is needed. The returned list is preceded by the projection nick of the result; usually the same as the provided $nick, but in some cases (for instance UTM) it may differ. =back =head2 Geometry =over 4 =item $obj-EB() Returns the area covered by the geo structure. Points will return zero. =item $obj-EB() Returns the bounding box of the object as four coordinates, respectively xmin, ymin, xmax, ymax. The values are expressed in the coordinate system of the object. =item $obj-EB() Returns a L which represent the middle of the object. It is the center of the bounding box. The values is cached, once computed. Be warned that the central point in one projection system may be quite different from the central point in some other projectionsystem . =item $obj-EB([$xmin, $ymin, $xmax, $ymax, [$proj]]) =item Geo::Shape-EB([$xmin, $ymin, $xmax, $ymax, [$proj]]) Returns a L which describes the outer bounds of the object called upon, counter-clockwise and left-bottom first. As class method, you need to specify the limits and the PROJection. =item $obj-EB($object, [$unit]) Calculate the distance between this object and some other object. For many combinations of objects this is not supported or only partially supported. This calculation is performed with L in accurate mode. The default $unit is kilometers. Other units are provided in the manual page of L. As extra unit, C and C are added as well as the C alias for kilometer. =item $obj-EB() Returns the length of the outer border of the object's components. For points, this returns zero. =back =head2 Display =over 4 =item $obj-EB($degrees, $pos, $neg) =item Geo::Shape-EB($degrees, $pos, $neg) Like L but without showing seconds. example: print $point->deg2dm(0.12, 'e', 'w'); print Geo::Shape->deg2dm(0.12, 'e', 'w'); =item $obj-EB($degrees, $pos, $neg) =item Geo::Shape-EB($degrees, $pos, $neg) Translate floating point $degrees into a "degrees minutes seconds" notation. An attempt is made to handle rounding errors. example: print $point->deg2dms(-12.34, 'E', 'W');' # --> 12d20'24"W print Geo::Shape->deg2dms(52.1234, 'E', 'W'); # --> 52d07'24"E =item $obj-EB($dms) =item Geo::Shape-EB($dms) Accepts for instance 3d12'24.123, 3d12"E, 3.12314w, n2.14, s3d12", -12d34, and returns floating point degrees. =back =head1 OVERLOAD =over 4 =item overload: B<'""' (stringification)> Returns a string "$proj($lat,$long)" or "$proj($x,$y)". The C<$proj> is the nickname you have assigned to the projection. =item overload: B<'bool' (truth value)> A point is always true: defined. =back =head1 DIAGNOSTICS =over 4 =item Error: distance calculation not implemented between a $kind and a $kind Only a subset of all objects can be used in the distance calculation. The limitation is purely caused by lack of time to implement this. =item Error: in() not implemented for a $class =back =head1 SEE ALSO This module is part of Geo-Point distribution version 0.96, built on January 21, 2014. Website: F All modules in this suite: L, L, L, L, L, L, L, L, and L. Please post questions or ideas to the mailinglist at F =head1 LICENSE Copyrights 2005-2014 by [Mark Overmeer]. For other contributors see ChangeLog. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See F Geo-Point-0.96/lib/Geo/Space.pod0000644000175000001440000001252112267473546017027 0ustar00markovusers00000000000000=encoding utf8 =head1 NAME Geo::Space - A collection of various items =head1 INHERITANCE Geo::Space is a Geo::Shape =head1 SYNOPSIS my $island1 = Geo::Line->filled(...); my $island2 = Geo::Space->new(...); my $islands = Geo::Space->new($island1, $island2) =head1 DESCRIPTION Where a L can only contains sets of nested polygons, the Space can contain anything you like: lines, points, and unrelated polygons. Extends L<"DESCRIPTION" in Geo::Shape|Geo::Shape/"DESCRIPTION">. =head1 METHODS Extends L<"METHODS" in Geo::Shape|Geo::Shape/"METHODS">. =head2 Constructors Extends L<"Constructors" in Geo::Shape|Geo::Shape/"Constructors">. =over 4 =item $obj-EB([$components], %options) =item Geo::Space-EB([$components], %options) When called as instance method, some defaults are copied from the object where the call is made upon. Usually called as class method. $components are L, L, L, L, L, L objects. -Option--Defined in--Default proj Geo::Shape see Geo::Proj::defaultProjection() =over 2 =item proj => LABEL =back =back =head2 Attributes Extends L<"Attributes" in Geo::Shape|Geo::Shape/"Attributes">. =over 4 =item $obj-EB($index, [$index, ...]) Returns the component (or components) with the specified $index(es). One L object in scalar context, and multiple in list context. =item $obj-EB() Returns a list of L objects, all located in this space. =item $obj-EB() Returns a list of L objects, which are defined as separate components. =item $obj-EB() Returns the number of components. =item $obj-EB() Returns true when all components are lines; L objects. =item $obj-EB() Returns true when all components are points; L objects. =item $obj-EB() Returns true when all components are closed lines; L objects each defined as ring. =item $obj-EB() Returns a list of L objects, which are defined as separate components. =item $obj-EB() Inherited, see L =item $obj-EB() Inherited, see L =back =head2 Projections Extends L<"Projections" in Geo::Shape|Geo::Shape/"Projections">. =over 4 =item $obj-EB(<$label|'utm'>) Inherited, see L =item $obj-EB($nick, @points) Inherited, see L =back =head2 Geometry Extends L<"Geometry" in Geo::Shape|Geo::Shape/"Geometry">. =over 4 =item $obj-EB() Returns the area enclosed by the combined components. Only useful when the points are in some orthogonal projection. =item $obj-EB() Inherited, see L =item $obj-EB() Inherited, see L =item $obj-EB([$xmin, $ymin, $xmax, $ymax, [$proj]]) =item Geo::Space-EB([$xmin, $ymin, $xmax, $ymax, [$proj]]) Inherited, see L =item $obj-EB($object, [$unit]) Inherited, see L =item $obj-EB() The length of the outer polygons of all components. Only useful in a orthogonal coordinate systems. =back =head2 Display Extends L<"Display" in Geo::Shape|Geo::Shape/"Display">. =over 4 =item $obj-EB($degrees, $pos, $neg) =item Geo::Space-EB($degrees, $pos, $neg) Inherited, see L =item $obj-EB($degrees, $pos, $neg) =item Geo::Space-EB($degrees, $pos, $neg) Inherited, see L =item $obj-EB($dms) =item Geo::Space-EB($dms) Inherited, see L =item $obj-EB([$projection]) Returns a string representation of the line, which is also used for stringification. example: =back =head1 OVERLOAD Extends L<"OVERLOAD" in Geo::Shape|Geo::Shape/"OVERLOAD">. =over 4 =item overload: B<'""' (stringification)> Inherited, see L =item overload: B<'bool' (truth value)> Inherited, see L =back =head1 DIAGNOSTICS =over 4 =item Error: distance calculation not implemented between a $kind and a $kind Only a subset of all objects can be used in the distance calculation. The limitation is purely caused by lack of time to implement this. =item Error: in() not implemented for a $class =back =head1 SEE ALSO This module is part of Geo-Point distribution version 0.96, built on January 21, 2014. Website: F All modules in this suite: L, L, L, L, L, L, L, L, and L. Please post questions or ideas to the mailinglist at F =head1 LICENSE Copyrights 2005-2014 by [Mark Overmeer]. For other contributors see ChangeLog. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See F Geo-Point-0.96/lib/Geo/Shape.pm0000644000175000001440000001215212267473543016663 0ustar00markovusers00000000000000# Copyrights 2005-2014 by [Mark Overmeer]. # For other contributors see ChangeLog. # See the manual pages for details on the licensing terms. # Pod stripped from pm file by OODoc 2.01. use strict; use warnings; package Geo::Shape; use vars '$VERSION'; $VERSION = '0.96'; use Geo::Proj; # defines wgs84 use Geo::Point (); use Geo::Line (); use Geo::Surface (); use Geo::Space (); use Geo::Distance (); use Math::Trig qw/deg2rad/; use Carp qw/croak confess/; use overload '""' => 'string' , bool => sub {1} , fallback => 1; sub new(@) { my $class = shift; (bless {}, $class)->init( {@_} ) } sub init($) { my ($self, $args) = @_; my $proj = $self->{G_proj} = $args->{proj} || Geo::Proj->defaultProjection->nick; croak "proj parameter must be a label, not a Geo::Proj object" if UNIVERSAL::isa($proj, 'Geo::Proj'); $self; } #--------------------------- sub proj() { shift->{G_proj} } sub proj4() { Geo::Proj->proj4(shift->{G_proj}) } #--------------------------- sub in($) { croak "ERROR: in() not implemented for a ".ref(shift) } sub projectOn($@) { # fast check: nothing to be done return () if @_<2 || $_[0]->{G_proj} eq $_[1]; my ($self, $projnew) = (shift, shift); my $projold = $self->{G_proj}; return ($projnew, @_) if $projold eq $projnew; if($projnew eq 'utm') { my $point = $_[0]; $point = Geo::Point->xy(@$point, $projold) if ref $point eq 'ARRAY'; $projnew = Geo::Proj->bestUTMprojection($point, $projold)->nick; return ($projnew, @_) if $projnew eq $projold; } my $points = Geo::Proj->to($projold, $projnew, \@_); ($projnew, @$points); } #--------------------------- my $geodist; sub distance($;$) { my ($self, $other, $unit) = (shift, shift, shift); $unit ||= 'kilometer'; unless($geodist) { $geodist = Geo::Distance->new; $geodist->formula('hsin'); $geodist->reg_unit(1 => 'radians'); $geodist->reg_unit(deg2rad(1) => 'degrees'); $geodist->reg_unit(km => 1, 'kilometer'); } my $proj = $self->proj; $other = $other->in($proj) if $other->proj ne $proj; if($self->isa('Geo::Point') && $other->isa('Geo::Point')) { return $self->distancePointPoint($geodist, $unit, $other); } die "ERROR: distance calculation not implemented between a " . ref($self) . " and a " . ref($other); } sub bboxRing(@) { my ($thing, $xmin, $ymin, $xmax, $ymax, $proj) = @_; if(@_==1 && ref $_[0]) # instance method without options { $proj = $thing->proj; ($xmin, $ymin, $xmax, $ymax) = $thing->bbox; } Geo::Line->new # just a little faster than calling ring() ( points => [ [$xmin,$ymin], [$xmax,$ymin], [$xmax,$ymax] , [$xmin,$ymax], [$xmin,$ymin] ] , proj => $proj , ring => 1 , bbox => [$xmin, $ymin, $xmax, $ymax] , clockwise => 0 ); } sub bbox() { confess "INTERNAL: bbox() not implemented for ".ref(shift) } sub bboxCenter() { my $self = shift; my ($xmin, $ymin, $xmax, $ymax) = $self->bbox; Geo::Point->xy(($xmin+$xmax)/2, ($ymin+$ymax)/2, $self->proj); } sub area() { confess "INTERNAL: area() not implemented for ".ref(shift) } sub perimeter() { confess "INTERNAL: perimeter() not implemented for ".ref(shift) } sub deg2dms($$$) { my ($thing, $degrees, $pos, $neg) = @_; $degrees -= 360 while $degrees > 180; $degrees += 360 while $degrees <= -180; my $sign = $pos; if($degrees < 0) { $sign = $neg; $degrees= -$degrees; } my $d = int $degrees; my $frac = ($degrees - $d) * 60; my $m = int($frac + 0.00001); my $s = ($frac - $m) * 60; $s = 0 if $s < 0.001; my $g = int($s + 0.00001); my $h = int(($s - $g) * 1000 + 0.0001); $h ? sprintf("%dd%02d'%02d.%03d\"$sign", $d, $m, $g, $h) : $s ? sprintf("%dd%02d'%02d\"$sign", $d, $m, $g) : $m ? sprintf("%dd%02d'$sign", $d, $m) : sprintf("%d$sign", $d); } sub deg2dm($$$) { my ($thing, $degrees, $pos, $neg) = @_; defined $degrees or return '(null)'; $degrees -= 360 while $degrees > 180; $degrees += 360 while $degrees <= -180; my $sign = $pos; if($degrees < 0) { $sign = $neg; $degrees= -$degrees; } my $d = int $degrees; my $frac = ($degrees - $d) * 60; my $m = int($frac + 0.00001); $m ? sprintf("%dd%02d'$sign", $d, $m) : sprintf("%d$sign", $d); } sub dms2deg($) { my ($thing, $dms) = @_; my $o = 'E'; $dms =~ s/^\s+//; if($dms =~ s/([ewsn])\s*$//i) { $o = uc $1 } elsif($dms =~ s/^([ewsn])\s*//i) { $o = uc $1 } if($dms =~ m/^( [+-]? \d+ (?: \.\d+)? ) [\x{B0}dD]? \s* (?: ( \d+ (?: \.\d+)? ) [\'mM\x{92}]? )? \s* (?: ( \d+ (?: \.\d+)? ) [\"sS]? )? /xi ) { my ($d, $m, $s) = ($1, $2||0, $3||0); my $deg = ($o eq 'W' || $o eq 'S' ? -1 : 1) * ($d + $m/60 + $s/3600); return $deg; } (); } 1; Geo-Point-0.96/lib/Geo/Line.pod0000644000175000001440000002656612267473546016701 0ustar00markovusers00000000000000=encoding utf8 =head1 NAME Geo::Line - a sequence of connected points =head1 INHERITANCE Geo::Line is a Geo::Shape Geo::Line is a Math::Polygon =head1 SYNOPSIS my $line = Geo::Line->new(points => [$p1, $p2]); my $line = Geo::Line->line($p1, $p2); my $ring = Geo::Line->ring($p1, $p2, $p3, $p1); my $ring = Geo::Line->ring($p1, $p2, $p3); my $plane = Geo::Line->filled($p1, $p2, $p3, $p1); my $plane = Geo::Line->filled($p1, $p2, $p3); =head1 DESCRIPTION A 2-dimensional sequence of connected points. The points will be forced to use the same projection. Extends L<"DESCRIPTION" in Math::Polygon|Math::Polygon/"DESCRIPTION">. Extends L<"DESCRIPTION" in Geo::Shape|Geo::Shape/"DESCRIPTION">. =head1 METHODS Extends L<"METHODS" in Math::Polygon|Math::Polygon/"METHODS">. Extends L<"METHODS" in Geo::Shape|Geo::Shape/"METHODS">. =head2 Constructors Extends L<"Constructors" in Math::Polygon|Math::Polygon/"Constructors">. Extends L<"Constructors" in Geo::Shape|Geo::Shape/"Constructors">. =over 4 =item Geo::Line-EB($string, [$projection]) Create a square from the $string. The coordinates can be separated by a comma (preferrably), or blanks. When the coordinates end on NSEW, the order does not matter, otherwise lat-long or xy order is presumed. This routine is very smart. It understands PROJLABEL: <4 coordinates in any order, but with NSEW> ... example: bbox from string my $x = '5n 2n 3e e12'; # coordinates in any order my $x = '5e , 2n, 3n, e12'; # coordinates in any order my $x = '2.12-23.1E, N1-4'; # stretches my $x = 'wgs84: 2-5e, 1-8n'; # starts with projection my $x = 'wgs84: e2d12' -3d, n1, n7d12'34"'; my ($xmin, $ymin, $xmax, $ymax, $proj) = Geo::Line->bboxFromString($x); my $p = Geo::Line->ringFromString($x); # When parsing user applications, you probably want: my $p = eval { Geo::Line->bboxFromString($x) }; warn $@ if $@; =item $obj-EB($points, %options) =item Geo::Line-EB($points, %options) The $points form a L and the filled is part of the geometrical shape. =item $obj-EB($points, %options) =item Geo::Line-EB($points, %options) construct a line, which will probably not have the same begin and end point. The $points are passed as L, and the other %options are passed to L as well. =item $obj-EB([%options]) =item Geo::Line-EB([%options]) When called as instance method, the projection, ring, and filled attributes are taken from the initiator, like a clone with modification. -Option --Defined in --Default bbox Math::Polygon undef clockwise Math::Polygon undef filled points proj Geo::Shape see Geo::Proj::defaultProjection() ring =over 2 =item bbox => ARRAY =item clockwise => BOOLEAN =item filled => BOOLEAN Implies ring. The filled of the ring is included in the geometrical shape. =item points => ARRAY-OF-POINTS|ARRAY-OF-COORDINATES With this option, you can specify either L objects, or coordinate pairs which will get transformed into such objects. WARNING: in that case, the coordinates must be in xy order. =item proj => LABEL =item ring => BOOLEAN The first point is the last point. When specified, you have to make sure that this is the case. If L is used to create this object, that routine will check/repair it for you. =back example: my $point = Geo::Point->xy(1, 2); my $line = Geo::Line->new ( points => [$point, [3,4], [5,6], $point] , ring => 1 ); my $clone = $line->new(filled => 1); =item $obj-EB($points, %options) =item Geo::Line-EB($points, %options) The first and last point will be made the same: if not yet, than a reference to the first point is appended to the list. A "ring" does not cover the internal. =item Geo::Line-EB($string, [$projection]) Calls L and then produces a ring object from than. Don't forget the C when you call this method. =back =head2 Attributes Extends L<"Attributes" in Math::Polygon|Math::Polygon/"Attributes">. Extends L<"Attributes" in Geo::Shape|Geo::Shape/"Attributes">. =over 4 =item $obj-EB($index, [$index, ..]) Returns the L for the point with the specified $index or indices. =item $obj-EB() In LIST context, this returns all points as separate scalars: each is a L with projection information. In SCALAR context, a reference to the coordinates is returned. With L, you get arrays with XY coordinates returned, but without the projection information. That will be much faster, but not sufficient for some uses. =item $obj-EB() Returns a true value is the internals of the ring of points are declared to belong to the shape. =item $obj-EB() Returns a true value if the sequence of points are a ring or filled: the first point is the last. =item $obj-EB() Inherited, see L =item $obj-EB() Inherited, see L =item $obj-EB($index, [$index,...]) Inherited, see L =item $obj-EB() Inherited, see L =item $obj-EB() Inherited, see L =item $obj-EB() Inherited, see L =back =head2 Projections Extends L<"Projections" in Geo::Shape|Geo::Shape/"Projections">. =over 4 =item $obj-EB(<$label|'utm'>) Inherited, see L =item $obj-EB($nick, @points) Inherited, see L =back =head2 Geometry Extends L<"Geometry" in Math::Polygon|Math::Polygon/"Geometry">. Extends L<"Geometry" in Geo::Shape|Geo::Shape/"Geometry">. =over 4 =item $obj-EB() Returns the area enclosed by the polygon. Only useful when the points are in some orthogonal projection. =item $obj-EB() The bounding box coordinates. These are more useful for rings than for open line pieces. =item $obj-EB() Inherited, see L =item $obj-EB([$xmin, $ymin, $xmax, $ymax, [$proj]]) =item Geo::Line-EB([$xmin, $ymin, $xmax, $ymax, [$proj]]) Inherited, see L =item $obj-EB(%options) Inherited, see L =item $obj-EB() Inherited, see L =item $obj-EB(<$xmin,$xmax,$ymin,$ymax>|$object) Clip the shape to the bounding box of $object, or the boxing parameters specified. A list of L objects is returned if anything is inside the object. On the moment L and L are used to do the job. In the future, that may change. =item $obj-EB() Inherited, see L =item $obj-EB($point) Inherited, see L =item $obj-EB() Inherited, see L =item $obj-EB($object, [$unit]) Inherited, see L =item $obj-EB(<$other | ARRAY,[$tolerance]> | $points) Inherited, see L =item $obj-EB() Inherited, see L =item $obj-EB() Inherited, see L =item $obj-EB() The length of the line, only useful in a orthogonal coordinate system (projection). See also L. =item $obj-EB() The length of the line on the ring. A check is performed that the ring is closed, but further this returns the result of L =item $obj-EB(<$other | ARRAY,[$tolerance]> | $points) Inherited, see L =item $obj-EB() Inherited, see L =back =head2 Transformations Extends L<"Transformations" in Math::Polygon|Math::Polygon/"Transformations">. =over 4 =item $obj-EB(%options) Inherited, see L =item $obj-EB(%options) Inherited, see L =item $obj-EB(%options) Inherited, see L =item $obj-EB(%options) Inherited, see L =item $obj-EB(%options) Inherited, see L =item $obj-EB(%options) Inherited, see L =back =head2 Clipping Extends L<"Clipping" in Math::Polygon|Math::Polygon/"Clipping">. =over 4 =item $obj-EB($box) Inherited, see L =item $obj-EB($box) Inherited, see L =back =head2 Display Extends L<"Display" in Math::Polygon|Math::Polygon/"Display">. Extends L<"Display" in Geo::Shape|Geo::Shape/"Display">. =over 4 =item $obj-EB($degrees, $pos, $neg) =item Geo::Line-EB($degrees, $pos, $neg) Inherited, see L =item $obj-EB($degrees, $pos, $neg) =item Geo::Line-EB($degrees, $pos, $neg) Inherited, see L =item $obj-EB($dms) =item Geo::Line-EB($dms) Inherited, see L =item $obj-EB() Inherited, see L =item $obj-EB([$projection]) Returns a string representation of the line, which is also used for stringification. The old method named C is deprecated. =back =head1 OVERLOAD Extends L<"OVERLOAD" in Geo::Shape|Geo::Shape/"OVERLOAD">. =over 4 =item overload: B<'""' (stringification)> Inherited, see L =item overload: B<'bool' (truth value)> Inherited, see L =back =head1 DIAGNOSTICS =over 4 =item Error: area requires a ring of points If you think you have a ring of points (a polygon), than do specify that when that object is instantiated (L or L). =item Error: distance calculation not implemented between a $kind and a $kind Only a subset of all objects can be used in the distance calculation. The limitation is purely caused by lack of time to implement this. =item Error: in() not implemented for a $class =item Error: perimeter requires a ring of points =back =head1 SEE ALSO This module is part of Geo-Point distribution version 0.96, built on January 21, 2014. Website: F All modules in this suite: L, L, L, L, L, L, L, L, and L. Please post questions or ideas to the mailinglist at F =head1 LICENSE Copyrights 2005-2014 by [Mark Overmeer]. For other contributors see ChangeLog. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See F Geo-Point-0.96/lib/Geo/Line.pm0000644000175000001440000001437112267473543016517 0ustar00markovusers00000000000000# Copyrights 2005-2014 by [Mark Overmeer]. # For other contributors see ChangeLog. # See the manual pages for details on the licensing terms. # Pod stripped from pm file by OODoc 2.01. use strict; use warnings; package Geo::Line; use vars '$VERSION'; $VERSION = '0.96'; use base qw/Geo::Shape Math::Polygon/; use Carp; use List::Util qw/min max/; use Scalar::Util qw/refaddr/; sub new(@) { my ($thing, %args) = @_; if(my $points = $args{points}) { @$points >= 2 or croak "ERROR: line needs at least two points"; my $proj = $args{proj}; foreach my $p (@$points) { next unless UNIVERSAL::isa($p, 'Geo::Point'); $proj ||= $p->proj; $p = [ $p->xy($proj) ]; # replace } $args{proj} = $proj; } ref $thing or return shift->Math::Polygon::new(%args); # instance method: clone! $thing->Math::Polygon::new ( ring => $thing->{GL_ring} , filled => $thing->{GL_fill} , proj => $thing->proj , %args ); } sub init($) { my ($self, $args) = @_; $self->Geo::Shape::init($args); $self->Math::Polygon::init($args); $self->{GL_ring} = $args->{ring} || $args->{filled}; $self->{GL_fill} = $args->{filled}; $self->{GL_bbox} = $args->{bbox}; $self; } sub line(@) { my $thing = shift; my @points; push @points, shift while @_ && ref $_[0]; $thing->new(points => \@points, @_); } sub ring(@) { my $thing = shift; my $self = $thing->line(@_, ring => 1); my $points = $self->points; my ($first, $last) = @$points[0, -1]; push @$points, $first unless $first->[0] == $last->[0] && $first->[1] == $last->[1]; $self; } sub filled(@) { my $thing = shift; $thing->ring(@_, filled => 1); } sub bboxFromString($;$) { my ($class, $string, $nick) = @_; $string =~ s/^\s+//; $string =~ s/\s+$//; return () unless length $string; # line starts with project label $nick = $1 if $string =~ s/^(\w+)\s*\:\s*//; # Split the line my @parts = $string =~ m/\,/ ? split(/\s*\,\s*/, $string) : ($string); # expand dashes @parts = map { m/^([nesw])(\d.*?)\s*\-\s*(\d.*?)\s*$/i ? ($1.$2, $1.$3) : m/^(\d.*?)([nesw])\s*\-\s*(\d.*?)\s*$/i ? ($2.$1, $2.$3) : m/^(\d.*?)\s*\-\s*(\d.*?)\s*([nesw])\s*$/i ? ($1.$3, $2.$3) : $_ } @parts; # split on blanks @parts = map { split /\s+/, $_ } @parts; # Now, the first word may be a projection. That is: any non-coordinate, # anything which starts with more than one letter. if($parts[0] =~ m/^[a-z_]{2}/i) { $nick = lc(shift @parts); # overrules default } $nick ||= Geo::Proj->defaultProjection; my $proj = Geo::Proj->projection($nick); die "ERROR: Too few values in $string (got @parts, expect 4)\n" if @parts < 4; die "ERROR: Too many values in $string (got @parts, expect 4)" if @parts > 4; unless($proj) { die "ERROR: No projection defined for $string\n"; return undef; } if(! $proj->proj4->isLatlong) { die "ERROR: can only handle latlong coordinates, on the moment\n"; } my(@lats, @longs); foreach my $part (@parts) { if($part =~ m/[ewEW]$/ || $part =~ m/^[ewEW]/) { my $lat = $class->dms2deg($part); defined $lat or die "ERROR: dms latitude coordinate not understood: $part\n"; push @lats, $lat; } else { my $long = $class->dms2deg($part); defined $long or die "ERROR: dms longitude coordinate not understood: $part\n"; push @longs, $long; } } die "ERROR: expect two lats and two longs, but got " . @lats."/".@longs."\n" if @lats!=2; (min(@lats), min(@longs), max(@lats), max(@longs), $nick); } sub ringFromString($;$) { my $class = shift; my ($xmin, $ymin, $xmax, $ymax, $nick) = $class->bboxFromString(@_) or return (); $class->bboxRing($xmin, $ymin, $xmax, $ymax, $nick); } sub geopoints() { my $self = shift; my $proj = $self->proj; map { Geo::Point->new(x => $_->[0], y => $_->[1], proj => $proj) } $self->points; } sub geopoint(@) { my $self = shift; my $proj = $self->proj; unless(wantarray) { my $p = $self->point(shift) or return (); return Geo::Point->(x => $p->[0], y => $p->[1], proj => $proj); } map { Geo::Point->(x => $_->[0], y => $_->[1], proj => $proj) } $self->point(@_); } sub isRing() { my $self = shift; return $self->{GL_ring} if defined $self->{GL_ring}; my ($first, $last) = $self->points(0, -1); $self->{GL_ring} = ($first->[0]==$last->[0] && $first->[1]==$last->[1]); } sub isFilled() { shift->{GL_fill} } #---------------- sub in($) { my ($self, $projnew) = @_; return $self if ! defined $projnew || $projnew eq $self->proj; # projnew can be 'utm' my ($realproj, @points) = $self->projectOn($projnew, $self->points); @points ? $self->new(points => \@points, proj => $realproj) : $self; } #---------------- sub equal($;$) { my $self = shift; my $other = shift; return 0 if $self->nrPoints != $other->nrPoints; $self->Math::Polygon::equal($other->in($self->proj), @_); } sub bbox() { shift->Math::Polygon::bbox } sub area() { my $self = shift; croak "ERROR: area requires a ring of points" unless $self->isRing; $self->Math::Polygon::area; } sub perimeter() { my $self = shift; croak "ERROR: perimeter requires a ring of points." unless $self->isRing; $self->Math::Polygon::perimeter; } sub length() { shift->Math::Polygon::perimeter } sub clip(@) { my $self = shift; my $proj = $self->proj; my @bbox = @_==1 ? $_[0]->bbox : @_; $self->isFilled ? $self->fillClip1(@bbox) : $self->lineClip(@bbox); } #---------------- sub toString(;$) { my ($self, $proj) = @_; my $line; if(defined $proj) { $line = $self->in($proj); } else { $proj = $self->proj; $line = $self; } my $type = $line->isFilled ? 'filled' : $line->isRing ? 'ring' : 'line'; "$type\[$proj](".$line->Math::Polygon::string.')'; } *string = \&toString; 1; Geo-Point-0.96/lib/Geo/Surface.pm0000644000175000001440000000564212267473543017221 0ustar00markovusers00000000000000# Copyrights 2005-2014 by [Mark Overmeer]. # For other contributors see ChangeLog. # See the manual pages for details on the licensing terms. # Pod stripped from pm file by OODoc 2.01. use strict; use warnings; package Geo::Surface; use vars '$VERSION'; $VERSION = '0.96'; use base 'Geo::Shape'; use Math::Polygon::Surface (); use Math::Polygon::Calc qw/polygon_bbox/; use List::Util qw/sum first/; use Carp; sub new(@) { my $thing = shift; my @lines; push @lines, shift while ref $_[0]; @lines or return (); my %args = @_; my $class; if(ref $thing) # instance method { $args{proj} ||= $thing->proj; $class = ref $thing; } else { $class = $thing; } my $proj = $args{proj}; unless($proj) { my $s = first { UNIVERSAL::isa($_, 'Geo::Shape') } @lines; $args{proj} = $proj = $s->proj if $s; } my $mps; if(@lines==1 && UNIVERSAL::isa($_, 'Math::Polygon::Surface')) { $mps = shift @lines; } else { my @polys; foreach (@lines) { push @polys , UNIVERSAL::isa($_, 'Geo::Line' ) ? [$_->in($proj)->points] : UNIVERSAL::isa($_, 'Math::Polygon') ? $_ : UNIVERSAL::isa($_, 'ARRAY' ) ? Math::Polygon->new(@$_) : croak "ERROR: Do not known what to do with $_"; } $mps = Math::Polygon::Surface->new(@polys); } $args{_mps} = $mps; $thing->SUPER::new(%args); } sub init($) { my ($self, $args) = @_; $self->SUPER::init($args); $self->{GS_mps} = $args->{_mps}; $self; } sub outer() { shift->{GS_mps}->outer } sub inner() { shift->{GS_mps}->inner } sub geoOuter() { my $self = shift; Geo::Line->new(points => [$self->outer->points], proj => $self->proj); } sub geoInner() { my $self = shift; my $proj = $self->proj; map { Geo::Line->new(points => [$_->points], proj => $proj) } $self->inner; } *geo_outer = \&geoOuter; *geo_inner = \&geoInner; #-------------- sub in($) { my ($self, $projnew) = @_; return $self if ! defined $projnew || $projnew eq $self->proj; my @newrings; foreach my $ring ($self->outer, $self->inner) { (undef, my @points) = $self->projectOn($projnew, $ring->points); push @newrings, \@points; } my $mp = Math::Polygon::Surface->new(@newrings); (ref $self)->new($mp, proj => $projnew); } sub bbox() { polygon_bbox shift->outer->points } sub area() { my $self = shift; my $area = $self->outer->area; $area -= $_->area for $self->inner; $area; } sub perimeter() { shift->outer->perimeter } sub toString(;$) { my ($self, $proj) = @_; my $surface; if(defined $proj) { $surface = $self->in($proj); } else { $proj = $self->proj; $surface = $self; } my $mps = $self->{GS_mps}->string; $mps =~ s/\n-/)\n -(/; "surface[$proj]\n ($mps)\n"; } *string = \&toString; 1; Geo-Point-0.96/lib/Geo/Proj.pm0000644000175000001440000001103112267473543016530 0ustar00markovusers00000000000000# Copyrights 2005-2014 by [Mark Overmeer]. # For other contributors see ChangeLog. # See the manual pages for details on the licensing terms. # Pod stripped from pm file by OODoc 2.01. use strict; use warnings; package Geo::Proj; use vars '$VERSION'; $VERSION = '0.96'; use Geo::Proj4 (); use Carp qw/croak/; use overload '""' => sub { shift->nick } , fallback => 1; sub import() { Geo::Proj->new ( nick => 'wgs84' , proj4 => '+proj=latlong +datum=WGS84 +ellps=WGS84' ); } my %projections; my $defproj; sub new(@) { my ($class, %args) = @_; my $proj = $projections{$args{nick} || 'dead'}; return $proj if defined $proj; my $self = (bless {}, $class)->init(\%args); $projections{$self->nick} = $self; $defproj ||= $self; $self; } sub init($) { my ($self, $args) = @_; my $nick = $self->{GP_nick} = $args->{nick} or croak "ERROR: nick required"; $self->{GP_srid} = $args->{srid}; my $proj4 = $args->{proj4} or croak "ERROR: proj4 parameter required"; if(ref $proj4 eq 'ARRAY') { $proj4 = Geo::Proj4->new(@$proj4); croak "ERROR: cannot create proj4: ".Geo::Proj4->error unless $proj4; } elsif(!ref $proj4) { $proj4 = Geo::Proj4->new($proj4); croak "ERROR: cannot create proj4: ".Geo::Proj4->error unless $proj4; } $self->{GP_proj4} = $proj4; $self->{GP_name} = $args->{name}; $self; } sub nick() {shift->{GP_nick}} sub name() { my $self = shift; my $name = $self->{GP_name}; return $name if defined $name; my $proj = $self->proj4; my $abbrev = $proj->projection or return $self->{nick}; my $def = $proj->type($abbrev); $def->{description}; } sub proj4(;$) { my $thing = shift; return $thing->{GP_proj4} unless @_; my $proj = $thing->projection(shift) or return undef; $proj->proj4; } sub srid() {shift->{GP_srid}} sub projection($) { my $which = $_[1]; UNIVERSAL::isa($which, __PACKAGE__) ? $which : $projections{$which}; } sub defaultProjection(;$) { my $thing = shift; if(@_) { my $proj = shift; $defproj = ref $proj ? $proj : $thing->projection($proj); } $defproj; } sub listProjections() { sort keys %projections } sub dumpProjections(;$) { my $class = shift; my $fh = shift || select; my $default = $class->defaultProjection; my $defnick = defined $default ? $default->nick : ''; foreach my $nick ($class->listProjections) { my $proj = $class->projection($nick); my $name = $proj->name; my $norm = $proj->proj4->normalized; $fh->print("$nick: $name".($defnick eq $nick ? ' (default)':'')."\n"); $fh->print(" $norm\n") if $norm ne $name; } } sub to($@) { my $thing = shift; my $myproj4 = ref $thing ? $thing->proj4 : __PACKAGE__->proj4(shift); my $toproj4 = __PACKAGE__->proj4(shift); $myproj4->transform($toproj4, shift); } # These methods may have been implemented in Geo::Point, however may get # supported by any external library later. Knowledge about projections # is as much as possible concentrated here. sub zoneForUTM($) { my ($thing, $point) = @_; my ($long, $lat) = $point->longlat; my $zone = ($lat >= 56 && $lat < 64) ? ( $long < 3 ? undef : $long < 12 ? 32 : undef ) : ($lat >= 72 && $lat < 84) ? ( $long < 0 ? undef : $long < 9 ? 31 : $long < 21 ? 33 : $long < 33 ? 35 : $long < 42 ? 37 : undef ) : undef; my $meridian = int($long/6)*6 + ($long < 0 ? -3 : +3); $zone ||= int(($meridian+180)/6) +1; my $letter = ($lat < -80 || $lat > 84) ? '' : ('C'..'H', 'J'..'N', 'P'..'X', 'X')[ ($lat+80)/8 ]; wantarray ? ($zone, $letter, $meridian) : defined $zone ? "$zone$letter" : undef; } sub bestUTMprojection($;$) { my ($thing, $point) = (shift, shift); my $proj = @_ ? shift : $point->proj; my ($zone, $letter, $meridian) = $thing->zoneForUTM($point); $thing->UTMprojection($proj, $zone); } sub UTMprojection($$) { my ($class, $base, $zone) = @_; $base ||= $class->defaultProjection; my $datum = UNIVERSAL::isa($base, __PACKAGE__) ? $base->proj4->datum :$base; $datum ||= 'wgs84'; my $label = "utm$zone-\L$datum\E"; my $proj = "+proj=utm +zone=$zone +datum=\U$datum\E" . " +ellps=\U$datum\E +units=m +no_defs"; Geo::Proj->new(nick => $label, proj4 => $proj); } 1; Geo-Point-0.96/lib/Geo/Surface.pod0000644000175000001440000001203212267473546017361 0ustar00markovusers00000000000000=encoding utf8 =head1 NAME Geo::Surface - A surface description. =head1 INHERITANCE Geo::Surface is a Geo::Shape =head1 SYNOPSIS my $island = Geo::Surface->new($outer, $lake1, $lake2); =head1 DESCRIPTION In this context, a "surface" is defined as one filled area with possible enclosures in one projection system. Extends L<"DESCRIPTION" in Geo::Shape|Geo::Shape/"DESCRIPTION">. =head1 METHODS Extends L<"METHODS" in Geo::Shape|Geo::Shape/"METHODS">. =head2 Constructors Extends L<"Constructors" in Geo::Shape|Geo::Shape/"Constructors">. =over 4 =item Geo::Surface-EB(<$surface | <$outer,$inner,...> >, %options) When called as instance method, some defaults are copied from the object where the call is made upon. You may either provide a L $surface, or a LIST of lines. In the latter case, the first line is the $outer polygon of the surface, and the other are all $inner enclosures: lakes. Lines are and L, L objects, or ARRAY of points. If no projection is specified, then the projection of the first Geo-encoded line will be used. -Option--Defined in--Default proj Geo::Shape see Geo::Proj::defaultProjection() =over 2 =item proj => LABEL =back =back =head2 Attributes Extends L<"Attributes" in Geo::Shape|Geo::Shape/"Attributes">. =over 4 =item $obj-EB() Returns a LIST of enclosed polygons, converted to L objects. =item $obj-EB() Returns the outer polygon as L object. =item $obj-EB() Returns a LIST of enclosed L objects. =item $obj-EB() Returns the outer L. =item $obj-EB() Inherited, see L =item $obj-EB() Inherited, see L =back =head2 Projections Extends L<"Projections" in Geo::Shape|Geo::Shape/"Projections">. =over 4 =item $obj-EB(<$label|'utm'>) Inherited, see L =item $obj-EB($nick, @points) Inherited, see L =back =head2 Geometry Extends L<"Geometry" in Geo::Shape|Geo::Shape/"Geometry">. =over 4 =item $obj-EB() Returns the area enclosed by the outer polygon, minus the erea of the enclosures. Only useful when the points are in some orthogonal projection. =item $obj-EB() The bounding box of outer surface polygon. =item $obj-EB() Inherited, see L =item $obj-EB([$xmin, $ymin, $xmax, $ymax, [$proj]]) =item Geo::Surface-EB([$xmin, $ymin, $xmax, $ymax, [$proj]]) Inherited, see L =item $obj-EB($object, [$unit]) Inherited, see L =item $obj-EB() The length of the outer polygon. Only useful in a orthogonal coordinate systems. =back =head2 Display Extends L<"Display" in Geo::Shape|Geo::Shape/"Display">. =over 4 =item $obj-EB($degrees, $pos, $neg) =item Geo::Surface-EB($degrees, $pos, $neg) Inherited, see L =item $obj-EB($degrees, $pos, $neg) =item Geo::Surface-EB($degrees, $pos, $neg) Inherited, see L =item $obj-EB($dms) =item Geo::Surface-EB($dms) Inherited, see L =item $obj-EB([$projection]) Returns a string representation of the line, which is also used for stringification. =back =head1 OVERLOAD Extends L<"OVERLOAD" in Geo::Shape|Geo::Shape/"OVERLOAD">. =over 4 =item overload: B<'""' (stringification)> Inherited, see L =item overload: B<'bool' (truth value)> Inherited, see L =back =head1 DIAGNOSTICS =over 4 =item Warning: Geo::Line is should be filled When L objects are used to compose a surface, each of them must be filled. Representation of rivers and such do not belong in a surface description. =item Error: distance calculation not implemented between a $kind and a $kind Only a subset of all objects can be used in the distance calculation. The limitation is purely caused by lack of time to implement this. =item Error: in() not implemented for a $class =item Error: not known what to do with $component =back =head1 SEE ALSO This module is part of Geo-Point distribution version 0.96, built on January 21, 2014. Website: F All modules in this suite: L, L, L, L, L, L, L, L, and L. Please post questions or ideas to the mailinglist at F =head1 LICENSE Copyrights 2005-2014 by [Mark Overmeer]. For other contributors see ChangeLog. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See F Geo-Point-0.96/MANIFEST0000644000175000001440000000065712267473551015144 0ustar00markovusers00000000000000ChangeLog MANIFEST META.yml Makefile.PL README lib/Geo/Line.pm lib/Geo/Line.pod lib/Geo/Point.pm lib/Geo/Point.pod lib/Geo/Proj.pm lib/Geo/Proj.pod lib/Geo/Shape.pm lib/Geo/Shape.pod lib/Geo/Space.pm lib/Geo/Space.pod lib/Geo/Surface.pm lib/Geo/Surface.pod t/09proj.t t/10dms.t t/11point.t t/12surface.t t/20pstr.t t/21lstr.t t/22rstr.t t/99pod.t META.json Module JSON meta-data (added by MakeMaker) Geo-Point-0.96/t/0000755000175000001440000000000012267473551014246 5ustar00markovusers00000000000000Geo-Point-0.96/t/12surface.t0000644000175000001440000000163312267243164016224 0ustar00markovusers00000000000000#!/usr/bin/perl # # Test contruction of a point # use strict; use warnings; use Test::More tests => 11; use Geo::Line; use Geo::Surface; use Geo::Proj; Geo::Proj->new(nick => 'wgs84', proj4 => '+proj=latlong +datum=WGS84'); # # outer from ARRAY # my $s1 = Geo::Surface->new([[1,2],[3,4],[5,6],[1,2]], proj => 'wgs84'); ok(defined $s1, 'simple outer'); isa_ok($s1, 'Geo::Surface'); is($s1->toString, <<_S); surface[wgs84] ([[1,2], [3,4], [5,6], [1,2]]) _S my $o1 = $s1->outer; isa_ok($o1, 'Math::Polygon'); my @p1 = $o1->points; cmp_ok(scalar @p1, '==', 4); is($o1->string, '[1,2], [3,4], [5,6], [1,2]'); my @i1 = $s1->inner; cmp_ok(scalar @i1, '==', 0); my $go1 = $s1->geo_outer; isa_ok($go1, 'Geo::Line'); is($go1->toString, 'line[wgs84]([1,2], [3,4], [5,6], [1,2])'); ### my $s2 = Geo::Surface->new($go1); is($s2->proj, 'wgs84'); is($s2->toString, <<_S); surface[wgs84] ([[1,2], [3,4], [5,6], [1,2]]) _S Geo-Point-0.96/t/09proj.t0000644000175000001440000000101112267243164015542 0ustar00markovusers00000000000000#!/usr/bin/perl -T # # Test contruction of a point # use strict; use warnings; use lib qw(. lib tests ../MathPolygon/lib ../../MathPolygon/lib); use Test::More tests => 8; my $gp = 'Geo::Proj'; use_ok($gp); my $p = $gp->new(nick => 'wgs84', proj4 => '+proj=latlong +datum=WGS84'); ok(defined $p); isa_ok($p, $gp); is($p->nick, 'wgs84'); my $p4 = $p->proj4; ok(defined $p4, 'got proj4'); isa_ok($p4, 'Geo::Proj4'); ok($p4->isLatlong); is($p4->normalized, '+proj=latlong +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0'); Geo-Point-0.96/t/11point.t0000644000175000001440000000360612267243164015726 0ustar00markovusers00000000000000#!/usr/bin/env perl # # Test contruction of a point # use strict; use warnings; use lib qw(. lib tests ../MathPolygon/lib ../../MathPolygon/lib); use Test::More tests => 42; use Geo::Point; use Geo::Proj; my $gp = 'Geo::Point'; Geo::Proj->new(nick => 'wgs84', proj4 => '+proj=latlong +datum=WGS84'); # # latlong # my $p = $gp->latlong(2,3, 'wgs84'); ok(defined $p, "created a point"); isa_ok($p, $gp); isa_ok($p, 'Geo::Shape'); cmp_ok($p->lat, '==', 2); cmp_ok($p->latitude, '==', 2); cmp_ok($p->long, '==', 3); cmp_ok($p->longitude, '==', 3); is($p->proj, 'wgs84'); is($p->string, 'point[wgs84](2.0000 3.0000)'); is($p->x, 3); is($p->y, 2); # # longlat # $p = $gp->longlat(4,5, 'wgs84'); ok(defined $p, "created a longlat point"); isa_ok($p, $gp); isa_ok($p, 'Geo::Shape'); cmp_ok($p->lat, '==', 5); cmp_ok($p->long, '==', 4); is($p->proj, 'wgs84'); is($p->string, 'point[wgs84](5.0000 4.0000)'); is($p->x, 4); is($p->y, 5); # # xy # my $utm = Geo::Proj->new(nick => 'utm-31', proj4 => "+proj=utm +zone=31 +datum=WGS84"); ok(defined $utm, 'created utm'); $p = $gp->xy(4,5,'utm-31'); ok(defined $p, "created a xy point"); isa_ok($p, $gp); isa_ok($p, 'Geo::Shape'); cmp_ok($p->x, '==', 4); cmp_ok($p->y, '==', 5); is($p->proj, 'utm-31'); is($p->string, 'point[utm-31](4.0000 5.0000)'); is($p->x, 4); is($p->y, 5); # # yx # $p = $gp->yx(4,5,'utm-31'); ok(defined $p, "created a xy point"); isa_ok($p, $gp); isa_ok($p, 'Geo::Shape'); cmp_ok($p->x, '==', 5); cmp_ok($p->y, '==', 4); is($p->proj, 'utm-31'); is($p->string, 'point[utm-31](5.0000 4.0000)'); is($p->x, 5); is($p->y, 4); # # distance # my $p1 = $gp->latlong(0, 1); my $p2 = $gp->latlong(1, 1); cmp_ok(abs($p1->distance($p2, 'nautical mile') - 60), '<', 0.1); isnt($p1->distance($p2, 'degrees'), 0); isnt($p1->distance($p2, 'radians'), 0); Geo-Point-0.96/t/99pod.t0000644000175000001440000000041212267243164015367 0ustar00markovusers00000000000000#!/usr/bin/perl use warnings; use strict; use Test::More; BEGIN { eval "use Test::Pod 1.00"; plan skip_all => "Test::Pod 1.00 required for testing POD" if $@; plan skip_all => "devel home uses OODoc" if $ENV{MARKOV_DEVEL}; } all_pod_files_ok(); Geo-Point-0.96/t/10dms.t0000644000175000001440000000275612267243164015364 0ustar00markovusers00000000000000#!/usr/bin/perl -T # # Test parsing of strings containing DMS # use strict; use warnings; use lib qw(. .. tests ../MathPolygon/lib ../../MathPolygon/lib); use Test::More tests => 16; use Geo::Point; my $pkg = 'Geo::Point'; # # DEGMS # is($pkg->deg2dms(0, 'e', 'w'), '0e', 'zero east'); is($pkg->deg2dms(1, 'e', 'w'), '1e', 'one east'); is($pkg->deg2dms(-1, 'e', 'w'), '1w', 'one west'); is($pkg->deg2dms( 3.14159265, 'E', 'W'), qq#3d08'29.733"E#, 'pi east'); is($pkg->deg2dms(-3.14159265, 'E', 'W'), qq#3d08'29.733"W#, 'pi west'); # # DMSEG # # avoid failures on rounding errors sub about($$) { my ($calc, $expect) = @_; my $ok = abs($calc - $expect) < 0.00001; warn "$calc => $expect\n" unless $ok; $ok; } ok(about($pkg->dms2deg( qq#3d 8'29.733"W# ), -3.1415925), 'un-pi west'); ok(about($pkg->dms2deg( qq#W3d8'29.733"# ), -3.1415925), 'un-pi west 2'); ok(about($pkg->dms2deg( qq#3d 8'29.733"E# ), 3.1415925), 'un-pi east'); ok(about($pkg->dms2deg( qq#E3d 8'29.733"# ), 3.1415925), 'un-pi east 2'); ok(about($pkg->dms2deg( qq#3d8'29.733"E# ), 3.1415925)); ok(about($pkg->dms2deg( "3.1415925" ), 3.1415925)); ok(about($pkg->dms2deg( qq#3d8'29"E# ), 3.141388889)); ok(about($pkg->dms2deg( qq#3d8'29E# ), 3.141388889)); ok(about($pkg->dms2deg( qq#3d8E# ), 3.13333333)); # # DMS # my $p = Geo::Point->latlong(3.12, 4.20); is($p->dms, qq#3d07'12"N, 4d12'E#, 'dms'); is($p->dm, qq#3d07'N, 4d12'E#, 'dm' ); Geo-Point-0.96/t/20pstr.t0000644000175000001440000000371012267243164015561 0ustar00markovusers00000000000000#!/usr/bin/perl -T # # Test parsing of points, a combination of two strings # (Geo::Point->fromString) # use strict; use warnings; use lib qw(. .. lib tests); use Test::More tests => 107; use Geo::Point; my $pkg = 'Geo::Point'; # Prepare sub check($$$$) { my ($string, $proj, $one, $two) = @_; my $point = $pkg->fromString($string); isa_ok($point, $pkg); is($point->proj, $proj); cmp_ok($point->x, '==', $one); cmp_ok($point->y, '==', $two); } my $w = Geo::Proj->projection('wgs84'); ok($w); my $u = Geo::Proj->new(nick => 'utm31-wgs84' , proj4 => "+proj=utm +zone=31 +datum=WGS84"); ok($u); ### lat long check("wgs84 2d30' 5d3", 'wgs84', 5.05, 2.5); check("wgs84 2d30'N 5d3", 'wgs84', 5.05, 2.5); check("wgs84 5d3 2d30'N", 'wgs84', 5.05, 2.5); check("wgs84 2d30' 5d3E", 'wgs84', 5.05, 2.5); check("wgs84 5d3E 2d30'", 'wgs84', 5.05, 2.5); check("wgs84 2d30' 5d3e", 'wgs84', 5.05, 2.5); check("wgs84 5d3e 2d30'", 'wgs84', 5.05, 2.5); check("wgs84 N2d30' 5d3", 'wgs84', 5.05, 2.5); check("wgs84 5d3 N2d30'", 'wgs84', 5.05, 2.5); check("wgs84 2d30' E5d3", 'wgs84', 5.05, 2.5); check("wgs84 E5d3 2d30'", 'wgs84', 5.05, 2.5); check("wgs84 2d30' e5d3", 'wgs84', 5.05, 2.5); check("wgs84 e5d3 2d30'", 'wgs84', 5.05, 2.5); check("wgs84: 2d30' 5d3e", 'wgs84', 5.05, 2.5); check("wgs84: 5d3e 2d30'", 'wgs84', 5.05, 2.5); check("wgs84: 2d30', 5d3e", 'wgs84', 5.05, 2.5); check("wgs84: 5d3e, 2d30'", 'wgs84', 5.05, 2.5); check("wgs84, 2d30', 5d3e", 'wgs84', 5.05, 2.5); check("wgs84, 5d3e, 2d30'", 'wgs84', 5.05, 2.5); is(Geo::Proj->defaultProjection, 'wgs84'); check("2d30', 5d3e", 'wgs84', 5.05, 2.5); check("5d3e, 2d30'", 'wgs84', 5.05, 2.5); ## utm check("utm: 31 12.34 5.678", 'utm31-wgs84', 12.34, 5.678); check("utm: 31,12.34,5.678", 'utm31-wgs84', 12.34, 5.678); check("utm: 31, 12.34, 5.678", 'utm31-wgs84', 12.34, 5.678); check("utm, 31, 12.34, 5.678", 'utm31-wgs84', 12.34, 5.678); check("utm 31 12.34 5.678", 'utm31-wgs84', 12.34, 5.678); Geo-Point-0.96/t/22rstr.t0000644000175000001440000000164512267243164015572 0ustar00markovusers00000000000000#!/usr/bin/perl -T # # Test parsing of bboxes into rings # (Geo::Line->ringFromString) # use strict; use warnings; use lib qw(. lib .. tests ../MathPolygon/lib ../../MathPolygon/lib); use Test::More tests => 24; use Geo::Point; my $pkg = 'Geo::Line'; # Prepare my $ring = $pkg->ringFromString("wgs84: e2d12'-3d, n1, n7d0'36"); my ($xmin, $ymin, $xmax, $ymax, $proj) = (2.2, 1, 3, 7.01, 'wgs84'); ok(defined $ring, 'ring created'); isa_ok($ring, $pkg); ok($ring->isRing); my @p = $ring->points; cmp_ok(scalar(@p), '==', 5); for my $p (@p) { is(ref $p, 'ARRAY'); cmp_ok(scalar(@$p), '==', 2); } cmp_ok($p[0][0], '==', $xmin); cmp_ok($p[0][1], '==', $ymin); cmp_ok($p[1][0], '==', $xmax); cmp_ok($p[1][1], '==', $ymin); cmp_ok($p[2][0], '==', $xmax); cmp_ok($p[2][1], '==', $ymax); cmp_ok($p[3][0], '==', $xmin); cmp_ok($p[3][1], '==', $ymax); cmp_ok($p[4][0], '==', $xmin); cmp_ok($p[4][1], '==', $ymin); Geo-Point-0.96/t/21lstr.t0000644000175000001440000000214112267243164015553 0ustar00markovusers00000000000000#!/usr/bin/perl -T # # Test parsing of bboxes # (Geo::Line->bboxFromString) # use strict; use warnings; use lib qw(. lib .. tests ../MathPolygon/lib ../../MathPolygon/lib); use Test::More tests => 41; use Geo::Point; use Geo::Proj; my $pkg = 'Geo::Line'; Geo::Proj->new(nick => 'wgs84', proj4 => '+proj=latlong +datum=WGS84'); # Prepare sub check($$$$$$) { my ($string, $xmin, $ymin, $xmax, $ymax, $proj) = @_; #warn "$string\n"; my @b = $pkg->bboxFromString($string); cmp_ok(@b, '==', 5); cmp_ok($b[0], '==', $xmin); cmp_ok($b[1], '==', $ymin); cmp_ok($b[2], '==', $xmax); cmp_ok($b[3], '==', $ymax); } is(Geo::Proj->defaultProjection, 'wgs84'); check("5n 2n 3e e12", 3, 2, 12, 5, 'wgs84'); check("5n , 2n , 3e , e12", 3, 2, 12, 5, 'wgs84'); check("5n,2n,3e,e12", 3, 2, 12, 5, 'wgs84'); check("2.12-23.1E, N1-4", 2.12, 1, 23.1, 4, 'wgs84'); check("W2.12-23.1, 1-4S", -23.1, -4, -2.12, -1, 'wgs84'); check("10N, 30E, 45N, 70E", 30, 10, 70, 45, 'wgs84'); check("wgs84: 2-5e, 1-8n", 2, 1, 5, 8, 'wgs84'); check("wgs84: e2d12'-3d, n1, n7d0'36", 2.2, 1, 3, 7.01, 'wgs84'); Geo-Point-0.96/META.json0000644000175000001440000000174312267473551015431 0ustar00markovusers00000000000000{ "abstract" : "Geographical structures", "author" : [ "Mark Overmeer" ], "dynamic_config" : 1, "generated_by" : "ExtUtils::MakeMaker version 6.64, CPAN::Meta::Converter version 2.120630", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "Geo-Point", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "requires" : { "Geo::Distance" : "0.06", "Geo::Proj4" : "1.01", "Math::Polygon" : "1.01", "Math::Trig" : "1", "Test::More" : "0.47" } } }, "release_status" : "stable", "version" : "0.96" }