Changes between Initial Version and Version 1 of PerlMapScriptExamples35ex14


Ignore:
Timestamp:
Jan 29, 2009, 6:59:45 AM (15 years ago)
Author:
jmckenna
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • PerlMapScriptExamples35ex14

    v1 v1  
     1= query_points.pl =
     2
     3Perl mapscript 3.6.4 example of creating a queryable layer of point objects, by creating them as Layer Features without an associated shape file or database connection. The points are in the perl program. The .map EXTENT must match the points you want to display. One other subtle point: The points layer in the map file must have a TEMPLATE for the layer to queryable, even thought it is not used.
     4----
     5{{{
     6#!perl
     7#!/usr/bin/perl
     8# This is an example of creating a layer of point objects (actually buoys in the Gulf of Maine, U.S.) It should be
     9# easily adaptable to any set of points.  It creates the points as features in the layer which means that they
     10# can still be retrieved using $layer->queryByPoint() even though no shape file or database connection exists
     11# for them. The layer has a connectiontype of MS_INLINE
     12# Author: Eric Bridger eric@gomoos.org eric@maine.com
     13# This has only been tested with mapserver 3.6.4
     14
     15use strict;
     16use mapscript;
     17use CGI ":cgi";
     18
     19my $q = new CGI;
     20my $msg = '';
     21
     22# A hash of points. First field will be the label.
     23my %points = (
     24    J0202 =>    {'longitude' => -67.0173,
     25                'latitude'  => 44.8911,
     26                },
     27    K0103 =>    {'longitude' =>  -66.0146,
     28                'latitude' => 45.2045,
     29                },
     30    E0105 =>    {'longitude' => -68.3578,
     31                'latitude' => 43.7148,
     32                },
     33    L0102 =>    {'longitude' => -66.5528,
     34                'latitude' => 43.6243,
     35                },
     36    F0105 =>    {'longitude' => -68.9983,
     37                'latitude' => 44.0555,
     38                },
     39    M0102 =>    {'longitude' => -67.8800,
     40                'latitude' => 43.4900,
     41                },
     42    A0104 =>    {'longitude' => -70.5665,
     43                'latitude' => 42.5185,
     44                },
     45    B0103 =>    {'longitude' => -70.4278,
     46                'latitude' => 43.1807,
     47                },
     48    I0104 =>    {'longitude' => -68.1087,
     49                'latitude' => 44.1058,
     50                },
     51    C0202 =>    {'longitude' => -70.0578,
     52                'latitude' => 43.5673,
     53                },
     54);
     55
     56my $image_name = sprintf("%0.10d",rand(1000000000)) . ".png";
     57# see points.map
     58my $map = new mapscript::mapObj("query_points.map");
     59
     60if(!$map){
     61    warn "New mapObj() error: $mapscript::ms_error->{message}\n";
     62}
     63
     64# Create a point object representing the mouse click on the map.
     65my ($x, $y) = get_click($q, $map);
     66
     67my $click_pt = undef;
     68if($x != 0 && $y != 0){
     69    $click_pt = new mapscript::pointObj();
     70    $click_pt->{x} = $x;
     71    $click_pt->{y} = $y;
     72}
     73
     74my $img = $map->prepareImage();
     75
     76if(!$img){
     77    warn "prepareImage() error: $mapscript::ms_error->{message}\n";
     78}
     79
     80my $layerObj = undef;
     81
     82# Add points as Features to the point layer. Save any info in a lookup table. The shape objects and the
     83# index into the lookup table will be the same.
     84$layerObj = $map->getLayerByName('points');
     85my $point = new mapscript::pointObj();
     86
     87# Queries will return index into this array.
     88my @point_lookup = ();
     89my $i = 0;
     90foreach my $point_id (keys %points){
     91    $point->{x} = $points{$point_id}{longitude};
     92    $point->{y} = $points{$point_id}{latitude};
     93    # Features require shape objects, which require lines, so create a single point line.
     94    my $line = new mapscript::lineObj();
     95    $line->add($point);
     96    my $shp = new mapscript::shapeObj($mapscript::MS_SHAPE_POINT);
     97    $shp->add($line);
     98    $shp->setBounds();
     99    $shp->{text} = $point_id;
     100    # set the shape index to the index into our lookup table.
     101    $shp->{index} = $i;
     102    if($layerObj->addFeature($shp) == -1){
     103        warn "addFeature failed\n";
     104    }
     105    push @point_lookup, $point_id;
     106    $i++;
     107}
     108
     109# add layer to map img.
     110$layerObj->draw($map, $img);
     111
     112
     113# Query based on the mouse click point.
     114if($click_pt){
     115    my $record = -1;
     116    $msg .= "<p>\n";
     117    $layerObj = $map->getLayerByName('points');
     118#   $msg .= "tolerance $layerObj->{tolerance}<br>\n";
     119#   $msg .= "connection type $layerObj->{connectiontype} ";
     120#   if($layerObj->{connectiontype} == $mapscript::MS_INLINE){
     121#       $msg .= " INLINE<br>";
     122#   }
     123#   if($layerObj->{connectiontype} == $mapscript::MS_SHAPEFILE){
     124#       $msg .= " SHAPEFILE<br>";
     125#   }
     126
     127    if($layerObj->queryByPoint($map,$click_pt,$mapscript::MS_SINGLE,0)){
     128        $msg .= "No Points found<br>\n";
     129    }else{
     130        my $results = $layerObj->{resultcache};
     131        my $num_results = $results->{numresults};
     132        $msg .= "Found $num_results points.<br>\n";
     133        # we only expect one result.
     134        my $rslt = $layerObj->getResult(0);
     135        # this is an index into the point lookup table.
     136        my $record = $rslt->{shapeindex};
     137        my $point_name = $point_lookup[$record];
     138        $msg .= "Click found point: $point_name.<br>\n";
     139    }
     140    $msg .= "</p>\n";
     141
     142}
     143
     144# display the click point
     145if($click_pt){
     146    $layerObj = $map->getLayerByName('click');
     147    $click_pt->draw($map, $layerObj, $img, undef, "Click");
     148}
     149
     150
     151$map->drawLabelCache($img);
     152
     153$img->saveImage($image_name, $mapscript::MS_PNG, $map->{transparent}, $map->{interlace}, 0);
     154
     155$img->free();
     156
     157# Output the HTML form and map
     158
     159print $q->header();
     160print $q->start_html(-title=>'MapServer - Dynamic Points', -bgcolor=>"#ffffff");
     161
     162print "<form name=\"pointmap\" action=\"query_points.pl\" method=\"GET\">\n";
     163print "<table border=\"1\" cellpadding=\"5\" cellspacing=\"2\">\n";
     164print "<tr>\n";
     165print "<td>\n";
     166print "<input border=\"2\" type=\"image\" name=\"img\" src=\"$image_name\">\n";
     167print "</td>\n";
     168print "</tr>\n";
     169print "</table>\n";
     170print "</form>\n";
     171print "$msg<br>\n";
     172print "<a href=\"query_points.pl\"> Start over </a><br>\n";
     173print "<p><br><br><br></p>\n";
     174
     175print $q->end_html();
     176# translate mouse click x,y into map longitude, latitude based on map extent. This is based on set_extent() in
     177# mapquakes.pl
     178
     179sub get_click {
     180    my ($q, $map) = @_;
     181    my ($x, $y, $cx, $cy) = (0,0,0,0);
     182    my $minx = $map->{extent}->{minx};
     183    my $miny = $map->{extent}->{miny};
     184    my $maxx = $map->{extent}->{maxx};
     185    my $maxy = $map->{extent}->{maxy};
     186
     187    if($q->param('img.x')) { # Make sure we got a click
     188        $x = $q->param('img.x');
     189        $y = $q->param('img.y');
     190
     191        $cx = ($maxx-$minx)/($map->{width}-1); # calculate cellsize in x and y
     192        $cy = ($maxy-$miny)/($map->{height}-1);
     193
     194        $x = $minx + $cx*$x; # change x,y from image to map coordinates
     195        $y = $maxy - $cy*$y;
     196    }
     197
     198    return ($x, $y);
     199}
     200}}}
     201
     202= query_points.map =
     203{{{
     204MAP
     205  STATUS ON
     206  EXTENT -71.5 39.5 -63.0 46.0
     207  SIZE 504 385
     208  IMAGETYPE PNG
     209  UNITS DD
     210
     211SYMBOL
     212  TYPE ELLIPSE
     213  NAME "circle"
     214  POINTS 1 1 END
     215  FILLED TRUE
     216END
     217
     218SYMBOL
     219  TYPE VECTOR
     220  NAME "plus"
     221  POINTS .5 0 .5 1 -99 -99 0 .5 1 .5 END
     222END
     223
     224LAYER
     225  NAME "points"
     226  TYPE POINT
     227  STATUS ON
     228  TOLERANCE 10
     229  # Need fake template for querys to work
     230  TEMPLATE "bogus.html"
     231  CLASS
     232    NAME "buoy"
     233    SYMBOL "circle"
     234    SIZE  8
     235    COLOR 255 0 0
     236    OUTLINECOLOR 0 0 0
     237    LABEL
     238      COLOR 255 0 0
     239      TYPE BITMAP
     240      SIZE MEDIUM
     241      POSITION AUTO
     242      PARTIALS FALSE
     243      BUFFER 2
     244    END # end of label
     245  END
     246END
     247LAYER
     248  NAME "click"
     249  TYPE POINT
     250  STATUS ON
     251  CLASS
     252    NAME "click"
     253    SYMBOL "plus"
     254    SIZE  6
     255    COLOR 0 0 0
     256    LABEL
     257      TYPE BITMAP
     258      SIZE TINY
     259      COLOR 0 0 0
     260      POSITION AUTO
     261      PARTIALS FALSE
     262      BUFFER 1
     263    END
     264  END
     265END
     266
     267END
     268}}}
     269----
     270back to PerlMapScript