Changes between Initial Version and Version 1 of PerlMapScriptExamples42ex1


Ignore:
Timestamp:
Jan 29, 2009, 7:17:31 AM (15 years ago)
Author:
jmckenna
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • PerlMapScriptExamples42ex1

    v1 v1  
     1= query_points42.pl =
     2{{{
     3#!perl
     4 #!/usr/bin/perl
     5# This has been tested with mapserver 4.2 beta3. I found that Perl mapscript4.0.2 was not quite ready for prime
     6# time.  Missing methods: class->getStyle(), colorObj support, etc. It illustrates some of the changes needed to
     7# adapt a mapscript3.6 application to mapscript4.2. Thanks to Sean Giles for all his work on mapscript.
     8########################
     9# This is an example of creating a layer of point objects (actually buoys in the Gulf of Maine, U.S.) It should be
     10# easily adaptable to any set of points.  It creates the points as features in the layer which means that they
     11# can still be retrieved using $layer->queryByPoint() even though no shape file or database connection exists
     12# for them.
     13# In this revised edition:
     14# a) the points are drawn using $point->draw(). This allows us to do a getClass() and getStyle() for each point
     15# and set style values  such as $class->{style}{size} for each point.
     16# b) We call addFeature() so that the layer is queryable, which is the main point.
     17# c) We use a numeric key value as the $shape->{index} which maps to our "database". This will be returned by
     18#    queryByPoint().
     19# d) No need to call $layer->draw() since we already called $point->draw(). Thus the features serve as
     20#    an invisible layer just for querying.
     21# Author: Eric Bridger eric@gomoos.org eric@maine.com
     22# Date:
     23# This has been tested with mapserver 4.2 beta3. It does not work with mapserver4.0.2
     24########################
     25
     26use strict;
     27use mapscript42;
     28use CGI ":cgi";
     29
     30$ENV{MS_ERRORFILE} = '/tmp/mapserver4.log';
     31
     32my $q = new CGI;
     33my $msg = '';
     34
     35# A hash of points. First field is the key value used in addFeature() and returned by queryByPoint().
     36# This could come from any external database, etc.
     37my %points = (
     38        10202 =>        {'longitude' => -67.0173,
     39                                'latitude'  => 44.8911,
     40                                'size'  => 5,
     41                                'label'  => 'one',
     42                                },
     43        20103 =>        {'longitude' =>  -66.0146,
     44                                'latitude' => 45.2045,
     45                                'size'  => 10,
     46                                'label'  => 'two',
     47                                },
     48        30105 =>        {'longitude' => -68.3578,
     49                                'latitude' => 43.7148,
     50                                'size'  => 12,
     51                                'label'  => 'three',
     52                                },
     53        40102 =>        {'longitude' => -66.5528,
     54                                'latitude' => 43.6243,
     55                                'size'  => 18,
     56                                'label'  => 'four',
     57                                },
     58        50105 =>        {'longitude' => -68.9983,
     59                                'latitude' => 44.0555,
     60                                'size'  => 20,
     61                                'label'  => 'five',
     62                                },
     63        60102 =>        {'longitude' => -67.8800,
     64                                'latitude' => 43.4900,
     65                                'size'  => 10,
     66                                'label'  => 'six',
     67                                },
     68        70104 =>        {'longitude' => -70.5665,
     69                                'latitude' => 42.5185,
     70                                'size'  => 10,
     71                                'label'  => 'seven',
     72                                },
     73        80103 =>        {'longitude' => -70.4278,
     74                                'latitude' => 43.1807,
     75                                'size'  => 10,
     76                                'label'  => 'eight',
     77                                },
     78        90104 =>        {'longitude' => -68.1087,
     79                                'latitude' => 44.1058,
     80                                'size'  => 8,
     81                                'label'  => 'nine',
     82                                },
     83        100202 =>       {'longitude' => -70.0578,
     84                                'latitude' => 43.5673,
     85                                'size'  => 15,
     86                                'label'  => 'ten',
     87                                },
     88);
     89
     90my $image_name = sprintf("tmp/%0.10d",rand(1000000000)) . ".png";
     91# see points42.map
     92my $map = new mapscript42::mapObj("points42.map");
     93
     94
     95if(!$map){
     96        warn "New mapObj() error: $mapscript42::ms_error->{message}\n";
     97}
     98
     99# Get symbol indexes from map's symbolset
     100my $circle_idx = $map->{symbolset}->index("circle");
     101my $plus_idx = $map->{symbolset}->index("plus");
     102
     103# Colors have changed in 4.2. No longer just an index, $clr_index = $map->addColor() is gone.
     104# You can also use $styleOjb->{color}->setRGB() and $class->{label}->{color}->setRGB();
     105my $blue = new mapscript42::colorObj(0,0,255);
     106my $red = new mapscript42::colorObj(255,0,0);
     107my $black = new mapscript42::colorObj(0,0,0);
     108
     109# Create a point object representing the mouse click on the map.
     110my ($x, $y) = get_click($q, $map);
     111
     112my $click_pt = undef;
     113if($x != 0 && $y != 0){
     114        $click_pt = new mapscript42::pointObj();
     115        $click_pt->{x} = $x;
     116        $click_pt->{y} = $y;
     117}
     118
     119# create an image for drawing.
     120my $img = $map->draw();
     121
     122if(!$img){
     123        warn "prepareImage() error: $mapscript42::ms_error->{message}\n";
     124}
     125
     126my $layerObj = undef;
     127
     128# Add points as Features to the point layer.
     129$layerObj = $map->getLayerByName('points');
     130
     131
     132# Queries will return index into this array.
     133foreach my $point_id (keys %points){
     134        my $point = new mapscript42::pointObj();
     135        $point->{x} = $points{$point_id}{longitude};
     136        $point->{y} = $points{$point_id}{latitude};
     137        # Features require shape objects, which require lines, so create a single point line.
     138    my $line = new mapscript42::lineObj();
     139        $line->add($point);
     140        my $shp = new mapscript42::shapeObj($mapscript42::MS_SHAPE_POINT);
     141        $shp->add($line);
     142        #$shp->setBounds();
     143        # Don't set any text, $point->draw() will draw the text.
     144        #$shp->{text} = $point_id;
     145        # set the shape index to our database key value.
     146        # the $shp->{index} can be any NUMERIC value. If our database key values were alphanumeric
     147        # we would need to use a lookup array and set $shp-{index} to 0,1,2,...
     148        # queryByPoint() results will return this value, but it must be numeric.
     149        $shp->{index} = $point_id;
     150        $layerObj->addFeature($shp);
     151        # we only have one class in this layer.
     152        my $class = $layerObj->getClass(0);
     153
     154        # TWO APPROACHES illustrated here.
     155        # NEW SYTLE OBJ
     156        #my $style = new mapscript42::styleObj();
     157        # OR
     158        # EXISTING STYLE OBJ: This picks up defaults from map file e.g. black outline color
     159        my $style = $class->getStyle(0);
     160        # Add new style.
     161        #my $style = new mapscript42::styleObj($class);
     162
     163        # point size based on our "database"
     164        $style->{size} = $points{$point_id}{size};
     165        if($point_id == 40102){
     166                $style->{symbol} = $plus_idx;
     167        }else{
     168                $style->{symbol} = $circle_idx;
     169        }
     170        #$style->{symbol} = $plus_idx;
     171
     172        # COLORS
     173        # just to illustrate assigning a reference to a colorObj.
     174        my $color = $red;
     175        if($point_id == 20103){
     176                $color = $black;
     177        }
     178        $style->{color} = $color;
     179
     180        # since this is a STYLE from the map file we don't need this.
     181        # it's in the map file.
     182        $style->{outlinecolor} = $black;
     183
     184        $class->{label}->{color} = $blue;
     185
     186        $point->draw($map, $layerObj, $img, undef, $points{$point_id}{label});
     187       
     188        # NEW STYLE must REMOVE if you inserted it.
     189        #$class->removeStyle(0);
     190}
     191
     192# Query based on the mouse click point.
     193if($click_pt){
     194        $msg .= "<p>\n";
     195        # this is un-needed.
     196        $layerObj = $map->getLayerByName('points');
     197       
     198        if($layerObj->queryByPoint($map,$click_pt,$mapscript42::MS_SINGLE,0)){
     199                $msg .= "No Points found<br>\n";
     200        }else{
     201                # In 4.2 $layerObj-{resultcache} is no longer used.
     202                # use $num_results = $layerObj->getNumResults() then
     203                # foreach my $i (0 .. $num_results-1){
     204                #    my $rslt = $layerObj->getResult($i);
     205                #}
     206                # we only expect one result.
     207                my $rslt = $layerObj->getResult(0);
     208                # this is the numeric value we used for the shape passed to addFeature() above.
     209                my $point_id = $rslt->{shapeindex};
     210                $msg .= "Click found point: $point_id.<br>\n";
     211                $msg .= "name is:  $points{$point_id}{label}.<br>\n";
     212                $msg .= "size is:  $points{$point_id}{size}.<br>\n";
     213                $msg .= "lat:  $points{$point_id}{latitude} long:  $points{$point_id}{longitude}.<br>\n";
     214
     215        }
     216        $msg .= "</p>\n";
     217
     218}
     219
     220# display the click point
     221if($click_pt){
     222        $layerObj = $map->getLayerByName('click');
     223        $click_pt->draw($map, $layerObj, $img, undef, "Click");
     224}
     225
     226$map->drawLabelCache($img);
     227
     228$img->save($image_name);
     229
     230# NOTA BENA Deconstructors (~) have been created for all mapscript objects. Don't call $imgObj->free().
     231# It will be removed, but now causes core dump.
     232#$img->free();
     233
     234# Output the HTML form and map
     235
     236print $q->header();
     237
     238print $q->start_html(-title=>'MapServer4.2 - Dynamic Points', -bgcolor=>"#ffffff");
     239
     240print "<form name=\"pointmap\" action=\"points42.cgi\" method=\"GET\">\n";
     241print "<table border=\"1\" cellpadding=\"5\" cellspacing=\"2\">\n";
     242print "<tr>\n";
     243print "<td>\n";
     244print "<input border=\"2\" type=\"image\" name=\"img\" src=\"$image_name\">\n";
     245print "</td>\n";
     246print "</tr>\n";
     247print "</table>\n";
     248print "</form>\n";
     249print "$msg<br>\n";
     250print "<p><br><br><br></p>\n";
     251
     252
     253print $q->end_html();
     254
     255# translate mouse click x,y into map longitude, latitude based on map extent. This is based on set_extent() in
     256# mapquakes.pl
     257
     258sub get_click {
     259        my ($q, $map) = @_;
     260        my ($x, $y, $cx, $cy) = (0,0,0,0);
     261        my $minx = $map->{extent}->{minx};
     262        my $miny = $map->{extent}->{miny};
     263        my $maxx = $map->{extent}->{maxx};
     264        my $maxy = $map->{extent}->{maxy};
     265
     266        if($q->param('img.x')) { # Make sure we got a click
     267                $x = $q->param('img.x');
     268                $y = $q->param('img.y');
     269
     270                $cx = ($maxx-$minx)/($map->{width}-1); # calculate cellsize in x and y
     271                $cy = ($maxy-$miny)/($map->{height}-1);
     272
     273                $x = $minx + $cx*$x; # change x,y from image to map coordinates
     274                $y = $maxy - $cy*$y;
     275        }
     276
     277        return ($x, $y);
     278}
     279}}}
     280
     281= points42.map =
     282{{{
     283MAP
     284  NAME "points42"
     285  STATUS ON
     286  EXTENT -71.5 39.5 -63.0 46.0
     287  SIZE 504 385
     288  IMAGETYPE PNG
     289  UNITS DD
     290  PROJECTION
     291     "proj=latlong"
     292  END
     293  OUTPUTFORMAT
     294    NAME PNG
     295    DRIVER "GD/PNG"
     296    MIMETYPE "image/png"
     297    # 24bit
     298    IMAGEMODE RGB
     299    # 8 bit psuedo color
     300    #IMAGEMODE PC256
     301    #EXTENSION "png"
     302  END
     303
     304SYMBOL
     305  TYPE ELLIPSE
     306  NAME "circle"
     307  POINTS 1 1 END
     308  FILLED TRUE
     309END
     310
     311SYMBOL
     312  TYPE VECTOR
     313  NAME "plus"
     314  POINTS .5 0 .5 1 -99 -99 0 .5 1 .5 END
     315END
     316
     317LAYER
     318  NAME "points"
     319  TYPE POINT
     320  STATUS ON
     321  TOLERANCE 10
     322  # Need fake template for querys to work
     323  TEMPLATE "bogus.html"
     324  CLASS
     325    NAME "buoy"
     326    STYLE
     327      SYMBOL "circle"
     328      SIZE 0
     329      COLOR 0 255 0
     330      OUTLINECOLOR 0 0 0
     331    END
     332    LABEL
     333      COLOR 255 0 0
     334      TYPE BITMAP
     335      SIZE MEDIUM
     336      POSITION AUTO
     337      PARTIALS FALSE
     338      BUFFER 2
     339    END # end of label
     340  END
     341  PROJECTION
     342    "proj=latlong"
     343  END
     344END
     345
     346LAYER
     347  NAME "click"
     348  TYPE POINT
     349  STATUS ON
     350  CLASS
     351    NAME "click"
     352    STYLE
     353      SYMBOL "plus"
     354      SIZE  6
     355      COLOR 0 0 0
     356    END
     357    LABEL
     358      TYPE BITMAP
     359      SIZE TINY
     360      COLOR 0 0 0
     361      POSITION AUTO
     362      PARTIALS FALSE
     363      BUFFER 1
     364    END
     365  END
     366END
     367
     368END
     369}}}
     370----
     371back to PerlMapScript