Changeset 559

Show
Ignore:
Timestamp:
11/23/04 23:19:36 (4 years ago)
Author:
kake
Message:

Huge-ass pile of changes to make geo stuff work worldwide.

Location:
trunk
Files:
5 added
17 modified

Legend:

Unmodified
Added
Removed
  • trunk/Build.PL

    r552 r559  
    9090  default  => "United Kingdom" 
    9191  }, 
     92{ question => "Contact email address for the site administrator?", 
     93  variable => "contact_email" 
     94  }, 
    9295{ question => "What language will the site be in? (Please give an ISO language code.)", 
    9396  variable => "default_language", 
    9497  default  => "en" 
    95   }, 
    96 { question => "Contact email address for the site administrator?", 
    97   variable => "contact_email" 
    9898  }, 
    9999{ question => "What's the name of the node to use for the text formatting rules link?", 
     
    219219} 
    220220 
     221# Now deal with the geo stuff. 
     222my $geo_handler; 
     223my $geo_handler_qu = "Distance calculation methods available are:" 
     224                   . "\n  1) British National Grid" 
     225                   . "\n  2) Irish National Grid" 
     226                   . "\n  3) UTM ellipsoid" 
     227                   . "\nWhich would you like to use?"; 
     228 
     229if ( $skip_config ) { 
     230    # We default to GB National Grid for historical reasons. 
     231    $geo_handler = $existing_config{geo_handler} || 1; 
     232} else { 
     233    my $choice; 
     234    until ( $choice ) { 
     235        my $def = $existing_config{geo_handler} || 1; 
     236        $choice = Module::Build->prompt("\n".$geo_handler_qu, $def); 
     237        $choice =~ s/^\s*//; 
     238        $choice =~ s/\s*$//; 
     239        unless ( $choice eq "1" or $choice eq "2" or $choice eq "3" ) { 
     240            undef $choice; 
     241        } 
     242    } 
     243    $geo_handler = $choice; 
     244} 
     245 
     246$geo_handler_qu =~ s/\n//gs; 
     247push @answers, { 
     248                 question => $geo_handler_qu, 
     249                 variable => "geo_handler", 
     250                 value    => $geo_handler, 
     251               }; 
     252 
     253if ( $geo_handler eq "3" ) { 
     254    my $ellipsoid; 
     255    if ( $skip_config ) { 
     256        $ellipsoid = $existing_config{ellipsoid} || "International"; 
     257    } else { 
     258        my $qu = "Which ellipsoid do you want to use? (eg 'Airy', 'WGS-84')"; 
     259        my $def = $existing_config{ellipsoid} || "International"; 
     260        my $choice = Module::Build->prompt("\n".$qu, $def); 
     261        $choice =~ s/^\s*//; 
     262        $choice =~ s/\s*$//; 
     263        push @answers, { 
     264                         question => $qu, 
     265                         variable => "ellipsoid", 
     266                         value    => $choice, 
     267                       }; 
     268    } 
     269} 
     270 
    221271# Create a user-friendly config file from answers to prompts. 
    222272open FILE, ">wiki.conf" or die "Can't open wiki.conf for writing: $!"; 
     
    245295        'CGI::Wiki::Plugin::Categoriser'  => 0, 
    246296        'CGI::Wiki::Plugin::Diff'         => '0.07', # earlier buggy 
    247         'CGI::Wiki::Plugin::Locator::UK'  => '0.09', 
     297        'CGI::Wiki::Plugin::Locator::Grid'=> 0, 
    248298        'CGI::Wiki::Plugin::RSS::ModWiki' => '0.06', # for fancy stuff 
    249299        'CGI::Wiki::Plugin::RSS::Reader'  => '1.3',  # earlier versions don't support RSS 2.0 
     
    265315        'Module::Build' => '0.18', # earlier doesn't install script files 
    266316        }, 
     317    recommends => { 
     318        'DBD::SQLite'         => 0, # for testing 
     319        'Test::HTML::Content' => 0, # for testing, oddly enough 
     320    }, 
    267321    dynamic_config => 1, 
    268322    create_makefile_pl => "passthrough" 
  • trunk/Changes

    r556 r559  
    1         Fixed bug relating to lat/long representation. 
    2         Removed debugging warn accidentally left in last release. 
     1 
     2        Made the geolocation stuff work worldwide.  Squeeeeeee! 
     3        You can now choose between doing your distance calculations with 
     4          the British National Grid, the Irish National Grid, or a UTM 
     5          ellipsoid.  If you wish to use anything other than the British 
     6          National Grid and you have pre-existing location data then you 
     7          will need to save an edit of each node with location data before 
     8          distance searches will work. 
     9        In less exciting news: 
     10          Fixed bug relating to lat/long representation. 
     11          Removed debugging warn accidentally left in last release. 
     12          Fixed some HTML validation errors. 
    313 
    4140.44    17 November 2004 
  • trunk/INSTALL

    r530 r559  
    155155 
    156156 
     157  "What language will the site be in? (Please give an ISO language code.)" 
     158 
     159eg "en" for English, "it" for Italian. 
     160See http://ftp.ics.uci.edu/pub/ietf/http/related/iso639.txt 
     161 
     162 
    157163  "What's the name of the node to use for the text formatting rules link?" 
    158164 
     
    162168might want to call the node "Text Formatting Examples", "Text 
    163169Formatting Rules", "House Style" or whatever. 
     170 
     171 
     172  "Distance calculation methods available are: 
     173      1) British National Grid 
     174      2) Irish National Grid 
     175      3) UTM ellipsoid 
     176   Which would you like to use?" 
     177 
     178  (and if you choose UTM ellipsoid) 
     179  "Which ellipsoid would you like to use? (eg 'Airy', 'WGS-84')" 
     180 
     181See http://www.vterrain.org/Projections/ for how this all works. 
     182A UTM (Universal Transverse Mercator) ellipsoid maps latitude and 
     183longitude to eastings and northings on a square grid, which allows 
     184more accurate distance calculations within the guide.  The British and 
     185Irish National Grids are scaled and parametrised versions of UTM 
     186ellipsoids (Airy 1830 in the British case, Modified Airy in the Irish). 
     187 
     188Please note that at the moment there is no provision for changing your 
     189mind later about which ellipsoid to use, but it shouldn't be too hard 
     190to write a conversion script so don't worry too much about picking the 
     191wrong one.  However do note that once you've entered some location 
     192data you should not change this value in the config file without running 
     193some kind of converter. 
     194 
     195If you decide to use the British or Irish National Grid, your users 
     196will be able to choose between entering location data as lat/long 
     197or as grid co-ordinates. 
     198 
     199You must have Geography::NationalGrid::GB installed to use the British 
     200National Grid, Geography::NationalGrid::IE to use the Irish National 
     201Grid, and Geo::Coordinates::UTM to use a UTM ellipsoid. 
     202 
    164203 
    165204* Custom templates and CSS 
  • trunk/PREREQUISITES

    r554 r559  
    1010CGI::Wiki::Plugin::Categoriser 
    1111CGI::Wiki::Plugin::Diff (version 0.07 or later) 
    12 CGI::Wiki::Plugin::Locator::UK (version 0.09 or later) 
     12CGI::Wiki::Plugin::Locator::Grid 
    1313CGI::Wiki::Plugin::RSS::ModWiki (version 0.06 or later) 
    1414CGI::Wiki::Plugin::RSS::Reader (version 1.3 or later) 
     
    2323) 
    2424File::Spec::Functions 
    25 Geography::NationalGrid 
     25( 
     26  Geography::NationalGrid::GB 
     27    -- or -- 
     28  Geography::NationalGrid::IE 
     29    -- or -- 
     30  Geo::Coordinates::UTM 
     31) 
    2632LWP::Simple 
    2733Module::Build (version 0.18 or later) 
  • trunk/lib/OpenGuides.pm

    r556 r559  
    55use CGI; 
    66use CGI::Wiki::Plugin::Diff; 
    7 use CGI::Wiki::Plugin::Locator::UK; 
     7use CGI::Wiki::Plugin::Locator::Grid; 
    88use OpenGuides::CGI; 
    99use OpenGuides::Template; 
     
    4646    $self->{wiki} = $wiki; 
    4747    $self->{config} = $args{config}; 
    48     my $locator = CGI::Wiki::Plugin::Locator::UK->new; 
     48    # Default to British National Grid for historical reasons. 
     49    my $geo_handler = $self->config->{_}{geo_handler} || 1; 
     50    my $locator; 
     51    if ( $geo_handler == 1 ) { 
     52        $locator = CGI::Wiki::Plugin::Locator::Grid->new( 
     53                                             x => "os_x",    y => "os_y" ); 
     54    } elsif ( $geo_handler == 2 ) { 
     55        $locator = CGI::Wiki::Plugin::Locator::Grid->new( 
     56                                             x => "osie_x",  y => "osie_y" ); 
     57    } else { 
     58        $locator = CGI::Wiki::Plugin::Locator::Grid->new( 
     59                                             x => "easting", y => "northing" ); 
     60    } 
    4961    $wiki->register_plugin( plugin => $locator ); 
    5062    $self->{locator} = $locator; 
     
    183195                 language      => $config->{_}->{default_language}, 
    184196               ); 
    185  
    186197 
    187198    # We've undef'ed $version above if this is the current version. 
     
    574585printing the output to STDOUT. 
    575586 
     587The geographical data that you should provide in the L<CGI> object 
     588depends on the handler you chose in C<wiki.conf>. 
     589 
     590=over 
     591 
     592=item * 
     593 
     594B<British National Grid> - provide either C<os_x> and C<os_y> or 
     595C<latitude> and C<longitude>; whichever set of data you give, it will 
     596be converted to the other and both sets will be stored. 
     597 
     598=item * 
     599 
     600B<Irish National Grid> - provide either C<osie_x> and C<osie_y> or 
     601C<latitude> and C<longitude>; whichever set of data you give, it will 
     602be converted to the other and both sets will be stored. 
     603 
     604=item * 
     605 
     606B<UTM ellipsoid> - provide C<latitude> and C<longitude>; these will be 
     607converted to easting and northing and both sets of data will be stored. 
     608 
     609=back 
     610 
    576611=cut 
    577612 
  • trunk/lib/OpenGuides/SuperSearch.pm

    r545 r559  
    11package OpenGuides::SuperSearch; 
    22use strict; 
    3 our $VERSION = '0.08'; 
     3our $VERSION = '0.09'; 
    44 
    55use CGI qw( :standard ); 
    6 use CGI::Wiki::Plugin::Locator::UK; 
     6use CGI::Wiki::Plugin::Locator::Grid; 
    77use File::Spec::Functions qw(:ALL); 
    88use OpenGuides::Template; 
     
    5555    $self->{head}     = $config->{_}{site_name} . " Search"; 
    5656 
    57     my $locator = CGI::Wiki::Plugin::Locator::UK->new; 
     57    my $geo_handler = $config->{_}{geo_handler}; 
     58    my %locator_params; 
     59    if ( $geo_handler == 1 ) { 
     60        %locator_params = ( x => "os_x", y => "os_y" ); 
     61    } elsif ( $geo_handler == 2 ) { 
     62        %locator_params = ( x => "osie_x", y => "osie_y" ); 
     63    } elsif ( $geo_handler == 3 ) { 
     64        %locator_params = ( x => "easting", y => "northing" ); 
     65    } 
     66 
     67    my $locator = CGI::Wiki::Plugin::Locator::Grid->new( %locator_params ); 
    5868    $wiki->register_plugin( plugin => $locator ); 
    5969    $self->{locator} = $locator; 
     
    142152    # Run a distance search if we have sufficient criteria. 
    143153    if ( defined $self->{distance_in_metres} 
    144          && ( 
    145                  ( defined $self->{lat}  && defined $self->{long} ) 
    146               || ( defined $self->{os_x} && defined $self->{os_y} ) 
    147             ) 
    148        ) { 
     154         && defined $self->{x} && defined $self->{y} ) { 
    149155        $doing_search = 1; 
    150156        $tt_vars{dist} = $self->{distance_in_metres}; 
    151         foreach my $param ( qw( os_x os_y lat long ) ) { 
     157        foreach my $param ( qw( os_x os_y osie_x osie_y latitude longitude )) { 
    152158            $tt_vars{$param} = $self->{$param}; 
    153159        } 
     
    469475} 
    470476 
     477=back 
     478 
     479=head1 SEARCHING BY DISTANCE 
     480 
     481To perform a distance search, you need to supply one of the following 
     482sets of criteria to specify the distance to search within, and the 
     483origin (centre) of the search: 
     484 
     485=over 
     486 
     487=item B<os_dist, os_x, and os_y> 
     488 
     489Only works if you chose to use British National Grid in wiki.conf 
     490 
     491=item B<osie_dist, osie_x, and osie_y> 
     492 
     493Only works if you chose to use Irish National Grid in wiki.conf 
     494 
     495=item B<latlong_dist, latitude, and longitude> 
     496 
     497Should always work, but has a habit of "finding" things a couple of 
     498metres away from themselves. 
     499 
     500=back 
     501 
     502You can perform both pure distance searches and distance searches in 
     503combination with text searches. 
     504 
     505=cut 
     506 
    471507# Note this is called after any text search is run, and it is only called 
    472508# if there are sufficient criteria to perform the search. 
    473509sub run_distance_search { 
    474510    my $self = shift; 
    475     my $os_x = $self->{os_x}; 
    476     my $os_y = $self->{os_y}; 
    477     my $lat  = $self->{lat}; 
    478     my $long = $self->{long}; 
     511    my $x    = $self->{x}; 
     512    my $y    = $self->{y}; 
    479513    my $dist = $self->{distance_in_metres}; 
    480514 
    481     my @close; 
    482     if ( defined $lat && defined $long ) { 
    483         @close = $self->{locator}->find_within_distance( 
    484                                                          lat    => $lat, 
    485                                                          long   => $long, 
    486                                                          metres => $dist, 
    487                                                        ); 
    488     } else { 
    489         @close = $self->{locator}->find_within_distance( 
    490                                                          os_x   => $os_x, 
    491                                                          os_y   => $os_y, 
    492                                                          metres => $dist, 
    493                                                        ); 
    494     } 
     515    my @close = $self->{locator}->find_within_distance( 
     516                                                        x      => $x, 
     517                                                        y      => $y, 
     518                                                        metres => $dist, 
     519                                                      ); 
     520 
    495521    if ( $self->{results} ) { 
    496522        my %close_hash = map { $_ => 1 } @close; 
     
    501527                my $distance = $self->_get_distance( 
    502528                                                     node => $node, 
    503                                                      lat  => $lat, 
    504                                                      long => $long, 
    505                                                      os_x => $os_x, 
    506                                                      os_y => $os_y, 
     529                                                     x    => $x, 
     530                                                     y    => $y, 
    507531                                                   ); 
    508532                $results{$node}{distance} = $distance; 
     
    517541            my $distance = $self->_get_distance ( 
    518542                                                     node => $node, 
    519                                                      lat  => $lat, 
    520                                                      long => $long, 
    521                                                      os_x => $os_x, 
    522                                                      os_y => $os_y, 
     543                                                     x    => $x, 
     544                                                     y    => $y, 
    523545                                                   ); 
    524546            $results{$node} = { 
     
    534556sub _get_distance { 
    535557    my ($self, %args) = @_; 
    536     my ($node, $lat, $long, $x, $y) = @args{ qw( node lat long os_x os_y ) }; 
    537     if ( defined $lat && defined $long ) { 
    538         return $self->{locator}->distance( 
    539                                            from_lat  => $lat, 
    540                                            from_long => $long, 
    541                                            to_node   => $node, 
    542                                            unit      => "metres" 
    543                                          ); 
    544     } else { 
    545         return $self->{locator}->distance( 
    546                                            from_os_x => $x, 
    547                                            from_os_y => $y, 
    548                                            to_node   => $node, 
    549                                            unit      => "metres" 
    550                                          ); 
    551     } 
     558    my ($node, $x, $y) = @args{ qw( node x y ) }; 
     559    return $self->{locator}->distance( 
     560                                       from_x  => $x, 
     561                                       from_y  => $y, 
     562                                       to_node => $node, 
     563                                       unit    => "metres" 
     564                                     ); 
    552565} 
    553566 
     
    556569    my %vars = %{ $vars_hashref || {} }; 
    557570 
     571    # Make sure that we don't have any data left over from previous invocation. 
     572    # This is useful for testing purposes at the moment and will be essential 
     573    # for mod_perl implementations. 
     574    delete $self->{x}; 
     575    delete $self->{y}; 
     576    delete $self->{distance_in_metres}; 
     577    delete $self->{search_string}; 
     578 
    558579    # Strip out any non-digits from distance and OS co-ords. 
    559     foreach my $param ( qw( os_x os_y os_dist latlong_dist ) ) { 
     580    foreach my $param ( qw( os_x os_y osie_x osie_y 
     581                            osie_dist os_dist latlong_dist ) ) { 
    560582        if ( defined $vars{$param} ) { 
    561583            $vars{$param} =~ s/[^0-9]//g; 
    562584            # 0 is an allowed value but the empty string isn't. 
    563585            delete $vars{$param} if $vars{$param} eq ""; 
    564             $self->{$param} = $vars{$param} if defined $vars{$param}; 
    565586        } 
    566587    } 
    567588 
    568589    # Latitude and longitude are also allowed '-' and '.' 
    569     foreach my $param( qw( lat long ) ) { 
     590    foreach my $param( qw( latitude longitude ) ) { 
    570591        if ( defined $vars{$param} ) { 
    571592            $vars{$param} =~ s/[^-\.0-9]//g; 
    572593            # 0 is an allowed value but the empty string isn't. 
    573594            delete $vars{$param} if $vars{$param} eq ""; 
    574             $self->{$param} = $vars{$param} if defined $vars{$param}; 
    575595        } 
    576596    } 
    577597 
    578     # Set $self->{distance_in_metres} depending on whether we got 
    579     # OS co-ords or lat/long. 
    580     if ( defined $self->{os_x} && defined $self->{os_y} 
    581          && defined $self->{os_dist} ) { 
    582         $self->{distance_in_metres} = $self->{os_dist}; 
    583     } elsif ( defined $self->{lat} && defined $self->{long} 
    584               && defined $self->{latlong_dist} ) { 
    585         $self->{distance_in_metres} = $self->{latlong_dist}; 
     598    # Set $self->{distance_in_metres}, $self->{x}, $self->{y}, 
     599    # depending on whether we got 
     600    # OS co-ords or lat/long.  Only store parameters if they're complete, 
     601    # and supported by our method of distance calculation. 
     602    if ( defined $vars{os_x} && defined $vars{os_y} && defined $vars{os_dist} 
     603         && $self->config->{_}{geo_handler} eq 1 ) { 
     604        $self->{x} = $vars{os_x}; 
     605        $self->{y} = $vars{os_y}; 
     606        $self->{distance_in_metres} = $vars{os_dist}; 
     607    } elsif ( defined $vars{osie_x} && defined $vars{osie_y} 
     608         && defined $vars{osie_dist} 
     609         && $self->config->{_}{geo_handler} eq 2 ) { 
     610        $self->{x} = $vars{osie_x}; 
     611        $self->{y} = $vars{osie_y}; 
     612        $self->{distance_in_metres} = $vars{osie_dist}; 
     613    } elsif ( defined $vars{latitude} && defined $vars{longitude} 
     614              && defined $vars{latlong_dist} ) { 
     615        # All handlers can do lat/long, but they all do it differently. 
     616        if ( $self->config->{_}{geo_handler} eq 1 ) { 
     617            require Geography::NationalGrid::GB; 
     618            my $point = Geography::NationalGrid::GB->new( 
     619                Latitude  => $vars{latitude}, 
     620                Longitude => $vars{longitude}, 
     621            ); 
     622            $self->{x} = $point->easting; 
     623            $self->{y} = $point->northing; 
     624        } elsif ( $self->config->{_}{geo_handler} eq 2 ) { 
     625            require Geography::NationalGrid::IE; 
     626            my $point = Geography::NationalGrid::IE->new( 
     627                Latitude  => $vars{latitude}, 
     628                Longitude => $vars{longitude}, 
     629            ); 
     630            $self->{x} = $point->easting; 
     631            $self->{y} = $point->northing; 
     632        } elsif ( $self->config->{_}{geo_handler} eq 3 ) { 
     633            require Geo::Coordinates::UTM; 
     634            my ($zone, $x, $y) = Geo::Coordinates::UTM::latlon_to_utm( 
     635                                                $self->config->{_}{ellipsoid}, 
     636                                                $vars{latitude}, 
     637                                                $vars{longitude}, 
     638                                              ); 
     639            $self->{x} = $x; 
     640            $self->{y} = $y; 
     641        } 
     642        $self->{distance_in_metres} = $vars{latlong_dist}; 
     643    } 
     644 
     645    # Store os_x etc so we can pass them to template. 
     646    foreach my $param ( qw( os_x os_y osie_x osie_y latitude longitude ) ) { 
     647        $self->{$param} = $vars{$param}; 
    586648    } 
    587649 
     
    607669sub process_template { 
    608670    my ($self, %args) = @_; 
     671 
    609672    my $tt_vars = $args{tt_vars} || {}; 
    610673    $tt_vars->{not_editable} = 1; 
  • trunk/lib/OpenGuides/Template.pm

    r555 r559  
    169169        $header = CGI::header( -cookie => $args{cookies} ); 
    170170    } 
     171 
     172    # vile hack 
     173    my %field_vars = OpenGuides::Template->extract_metadata_vars( 
     174                                        wiki                 => $args{wiki}, 
     175                                        config               => $config, 
     176                                        set_coord_field_vars => 1, 
     177                                        metadata => {}, 
     178                                                           ); 
     179    $tt_vars = { %field_vars, %$tt_vars }; 
     180 
    171181    my $output; 
    172182    $tt->process( $args{template}, $tt_vars, \$output ); 
     
    211221C<metadata> and C<cgi_obj> then C<metadata> will take precedence, but 
    212222don't do that. 
     223 
     224The variables C<dist_field>, C<coord_field_1>, C<coord_field_1_name>, 
     225C<coord_field_1_value>, C<coord_field_2>, C<coord_field_2_name>, and 
     226C<coord_field_2_value>, which are used to create various forms, will 
     227only be set if I<either> C<metadata> is supplied I<or> 
     228C<set_coord_field_vars> is true, to prevent these values from being 
     229stored in the database on a node commit. 
    213230 
    214231=cut 
     
    268285 
    269286    if ( $args{metadata} ) { 
    270         foreach my $var ( qw( phone fax address postcode os_x os_y 
    271                               latitude longitude map_link website) ) { 
     287        foreach my $var ( qw( phone fax address postcode os_x os_y osie_x 
     288                              osie_y latitude longitude map_link website) ) { 
    272289            $vars{$var} = $metadata{$var}[0]; 
    273290        } 
     291        # Data for the distance search forms on the node display. 
     292        my $geo_handler = $config->{_}{geo_handler} || 1; 
     293        if ( $geo_handler == 1 ) { 
     294            %vars = ( 
     295                      %vars, 
     296                      coord_field_1       => "os_x", 
     297                      coord_field_2       => "os_y", 
     298                      dist_field          => "os_dist", 
     299                      coord_field_1_name  => "OS X coordinate", 
     300                      coord_field_2_name  => "OS Y coordinate", 
     301                      coord_field_1_value => $metadata{os_x}[0], 
     302                      coord_field_2_value => $metadata{os_y}[0], 
     303                    ); 
     304        } elsif ( $geo_handler == 2 ) { 
     305            %vars = ( 
     306                      %vars, 
     307                      coord_field_1       => "osie_x", 
     308                      coord_field_2       => "osie_y", 
     309                      dist_field          => "osie_dist", 
     310                      coord_field_1_name  =>"Irish National Grid X coordinate", 
     311                      coord_field_2_name  =>"Irish National Grid Y coordinate", 
     312                      coord_field_1_value => $metadata{osie_x}[0], 
     313                      coord_field_2_value => $metadata{osie_y}[0], 
     314                    ); 
     315        } else { 
     316            %vars = ( 
     317                      %vars, 
     318                      coord_field_1       => "latitude", 
     319                      coord_field_2       => "longitude", 
     320                      dist_field          => "latlong_dist", 
     321                      coord_field_1_name  => "Latitude", 
     322                      coord_field_2_name  => "Longitude", 
     323                      coord_field_1_value => $metadata{latitude}[0], 
     324                      coord_field_2_value => $metadata{longitude}[0], 
     325                    ); 
     326        } 
    274327    } else {