Skip to content

PerlMapScriptExamples35ex14

Thomas Bonfort edited this page Apr 6, 2012 · 2 revisions

Perl 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.

#!perl                                                                                                                                                                                                                                                                                                                                                                                                        
#!/usr/bin/perl                                                                                                                                                                                                                                                                                                                                                                                               
# This is an example of creating a layer of point objects (actually buoys in the Gulf of Maine, U.S.) It should be                                                                                                                                                                                                                                                                                            
# easily adaptable to any set of points.  It creates the points as features in the layer which means that they                                                                                                                                                                                                                                                                                                
# can still be retrieved using $layer->queryByPoint() even though no shape file or database connection exists                                                                                                                                                                                                                                                                                                 
# for them. The layer has a connectiontype of MS_INLINE                                                                                                                                                                                                                                                                                                                                                       
# Author: Eric Bridger [email protected] [email protected]                                                                                                                                                                                                                                                                                                                                                         
# This has only been tested with mapserver 3.6.4                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                              
use strict;                                                                                                                                                                                                                                                                                                                                                                                                   
use mapscript;                                                                                                                                                                                                                                                                                                                                                                                                
use CGI ":cgi";                                                                                                                                                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                                                                                                                                              
my $q = new CGI;                                                                                                                                                                                                                                                                                                                                                                                              
my $msg = '';                                                                                                                                                                                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                                                                                                                                                                                              
# A hash of points. First field will be the label.                                                                                                                                                                                                                                                                                                                                                            
my %points = (                                                                                                                                                                                                                                                                                                                                                                                                
    J0202 =>    {'longitude' => -67.0173,                                                                                                                                                                                                                                                                                                                                                                     
                'latitude'  => 44.8911,                                                                                                                                                                                                                                                                                                                                                                       
                },                                                                                                                                                                                                                                                                                                                                                                                            
    K0103 =>    {'longitude' =>  -66.0146,                                                                                                                                                                                                                                                                                                                                                                    
                'latitude' => 45.2045,                                                                                                                                                                                                                                                                                                                                                                        
                },                                                                                                                                                                                                                                                                                                                                                                                            
    E0105 =>    {'longitude' => -68.3578,                                                                                                                                                                                                                                                                                                                                                                     
                'latitude' => 43.7148,                                                                                                                                                                                                                                                                                                                                                                        
                },                                                                                                                                                                                                                                                                                                                                                                                            
    L0102 =>    {'longitude' => -66.5528,                                                                                                                                                                                                                                                                                                                                                                     
                'latitude' => 43.6243,                                                                                                                                                                                                                                                                                                                                                                        
                },                                                                                                                                                                                                                                                                                                                                                                                            
    F0105 =>    {'longitude' => -68.9983,                                                                                                                                                                                                                                                                                                                                                                     
                'latitude' => 44.0555,                                                                                                                                                                                                                                                                                                                                                                        
                },                                                                                                                                                                                                                                                                                                                                                                                            
    M0102 =>    {'longitude' => -67.8800,                                                                                                                                                                                                                                                                                                                                                                     
                'latitude' => 43.4900,                                                                                                                                                                                                                                                                                                                                                                        
                },                                                                                                                                                                                                                                                                                                                                                                                            
    A0104 =>    {'longitude' => -70.5665,                                                                                                                                                                                                                                                                                                                                                                     
                'latitude' => 42.5185,                                                                                                                                                                                                                                                                                                                                                                        
                },                                                                                                                                                                                                                                                                                                                                                                                            
    B0103 =>    {'longitude' => -70.4278,                                                                                                                                                                                                                                                                                                                                                                     
                'latitude' => 43.1807,                                                                                                                                                                                                                                                                                                                                                                        
                },                                                                                                                                                                                                                                                                                                                                                                                            
    I0104 =>    {'longitude' => -68.1087,                                                                                                                                                                                                                                                                                                                                                                     
                'latitude' => 44.1058,                                                                                                                                                                                                                                                                                                                                                                        
                },                                                                                                                                                                                                                                                                                                                                                                                            
    C0202 =>    {'longitude' => -70.0578,                                                                                                                                                                                                                                                                                                                                                                     
                'latitude' => 43.5673,                                                                                                                                                                                                                                                                                                                                                                        
                },                                                                                                                                                                                                                                                                                                                                                                                            
);                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                              
my $image_name = sprintf("%0.10d",rand(1000000000)) . ".png";                                                                                                                                                                                                                                                                                                                                                 
# see points.map                                                                                                                                                                                                                                                                                                                                                                                              
my $map = new mapscript::mapObj("query_points.map");                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                              
if(!$map){                                                                                                                                                                                                                                                                                                                                                                                                    
    warn "New mapObj() error: $mapscript::ms_error->{message}\n";                                                                                                                                                                                                                                                                                                                                             
}                                                                                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                                                                                              
# Create a point object representing the mouse click on the map.                                                                                                                                                                                                                                                                                                                                              
my ($x, $y) = get_click($q, $map);                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                              
my $click_pt = undef;                                                                                                                                                                                                                                                                                                                                                                                         
if($x != 0 && $y != 0){                                                                                                                                                                                                                                                                                                                                                                                       
    $click_pt = new mapscript::pointObj();                                                                                                                                                                                                                                                                                                                                                                    
    $click_pt->{x} = $x;                                                                                                                                                                                                                                                                                                                                                                                      
    $click_pt->{y} = $y;                                                                                                                                                                                                                                                                                                                                                                                      
}                                                                                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                                                                                              
my $img = $map->prepareImage();                                                                                                                                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                                                                                                                                              
if(!$img){                                                                                                                                                                                                                                                                                                                                                                                                    
    warn "prepareImage() error: $mapscript::ms_error->{message}\n";                                                                                                                                                                                                                                                                                                                                           
}                                                                                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                                                                                              
my $layerObj = undef;                                                                                                                                                                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                                                                                                              
# Add points as Features to the point layer. Save any info in a lookup table. The shape objects and the                                                                                                                                                                                                                                                                                                       
# index into the lookup table will be the same.                                                                                                                                                                                                                                                                                                                                                               
$layerObj = $map->getLayerByName('points');                                                                                                                                                                                                                                                                                                                                                                   
my $point = new mapscript::pointObj();                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                              
# Queries will return index into this array.                                                                                                                                                                                                                                                                                                                                                                  
my @point_lookup = ();                                                                                                                                                                                                                                                                                                                                                                                        
my $i = 0;                                                                                                                                                                                                                                                                                                                                                                                                    
foreach my $point_id (keys %points){                                                                                                                                                                                                                                                                                                                                                                          
    $point->{x} = $points{$point_id}{longitude};                                                                                                                                                                                                                                                                                                                                                              
    $point->{y} = $points{$point_id}{latitude};                                                                                                                                                                                                                                                                                                                                                               
    # Features require shape objects, which require lines, so create a single point line.                                                                                                                                                                                                                                                                                                                     
    my $line = new mapscript::lineObj();                                                                                                                                                                                                                                                                                                                                                                      
    $line->add($point);                                                                                                                                                                                                                                                                                                                                                                                       
    my $shp = new mapscript::shapeObj($mapscript::MS_SHAPE_POINT);                                                                                                                                                                                                                                                                                                                                            
    $shp->add($line);                                                                                                                                                                                                                                                                                                                                                                                         
    $shp->setBounds();                                                                                                                                                                                                                                                                                                                                                                                        
    $shp->{text} = $point_id;                                                                                                                                                                                                                                                                                                                                                                                 
    # set the shape index to the index into our lookup table.                                                                                                                                                                                                                                                                                                                                                 
    $shp->{index} = $i;                                                                                                                                                                                                                                                                                                                                                                                       
    if($layerObj->addFeature($shp) == -1){                                                                                                                                                                                                                                                                                                                                                                    
        warn "addFeature failed\n";                                                                                                                                                                                                                                                                                                                                                                           
    }                                                                                                                                                                                                                                                                                                                                                                                                         
    push @point_lookup, $point_id;                                                                                                                                                                                                                                                                                                                                                                            
    $i++;                                                                                                                                                                                                                                                                                                                                                                                                     
}                                                                                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                                                                                              
# add layer to map img.                                                                                                                                                                                                                                                                                                                                                                                       
$layerObj->draw($map, $img);                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                              
# Query based on the mouse click point.                                                                                                                                                                                                                                                                                                                                                                       
if($click_pt){                                                                                                                                                                                                                                                                                                                                                                                                
    my $record = -1;                                                                                                                                                                                                                                                                                                                                                                                          
    $msg .= "<p>\n";                                                                                                                                                                                                                                                                                                                                                                                          
    $layerObj = $map->getLayerByName('points');                                                                                                                                                                                                                                                                                                                                                               
#   $msg .= "tolerance $layerObj->{tolerance}<br>\n";                                                                                                                                                                                                                                                                                                                                                         
#   $msg .= "connection type $layerObj->{connectiontype} ";                                                                                                                                                                                                                                                                                                                                                   
#   if($layerObj->{connectiontype} == $mapscript::MS_INLINE){                                                                                                                                                                                                                                                                                                                                                 
#       $msg .= " INLINE<br>";                                                                                                                                                                                                                                                                                                                                                                                
#   }                                                                                                                                                                                                                                                                                                                                                                                                         
#   if($layerObj->{connectiontype} == $mapscript::MS_SHAPEFILE){                                                                                                                                                                                                                                                                                                                                              
#       $msg .= " SHAPEFILE<br>";                                                                                                                                                                                                                                                                                                                                                                             
#   }                                                                                                                                                                                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                                                                                                              
    if($layerObj->queryByPoint($map,$click_pt,$mapscript::MS_SINGLE,0)){                                                                                                                                                                                                                                                                                                                                      
        $msg .= "No Points found<br>\n";                                                                                                                                                                                                                                                                                                                                                                      
    }else{                                                                                                                                                                                                                                                                                                                                                                                                    
        my $results = $layerObj->{resultcache};                                                                                                                                                                                                                                                                                                                                                               
        my $num_results = $results->{numresults};                                                                                                                                                                                                                                                                                                                                                             
        $msg .= "Found $num_results points.<br>\n";                                                                                                                                                                                                                                                                                                                                                           
        # we only expect one result.                                                                                                                                                                                                                                                                                                                                                                          
        my $rslt = $layerObj->getResult(0);                                                                                                                                                                                                                                                                                                                                                                   
        # this is an index into the point lookup table.                                                                                                                                                                                                                                                                                                                                                       
        my $record = $rslt->{shapeindex};                                                                                                                                                                                                                                                                                                                                                                     
        my $point_name = $point_lookup[$record];                                                                                                                                                                                                                                                                                                                                                              
        $msg .= "Click found point: $point_name.<br>\n";                                                                                                                                                                                                                                                                                                                                                      
    }                                                                                                                                                                                                                                                                                                                                                                                                         
    $msg .= "</p>\n";                                                                                                                                                                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                                                                                                              
}                                                                                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                                                                                              
# display the click point                                                                                                                                                                                                                                                                                                                                                                                     
if($click_pt){                                                                                                                                                                                                                                                                                                                                                                                                
    $layerObj = $map->getLayerByName('click');                                                                                                                                                                                                                                                                                                                                                                
    $click_pt->draw($map, $layerObj, $img, undef, "Click");                                                                                                                                                                                                                                                                                                                                                   
}                                                                                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                              
$map->drawLabelCache($img);                                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                                                                                              
$img->saveImage($image_name, $mapscript::MS_PNG, $map->{transparent}, $map->{interlace}, 0);                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                              
$img->free();                                                                                                                                                                                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                                                                                                                                                                                              
# Output the HTML form and map                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                              
print $q->header();                                                                                                                                                                                                                                                                                                                                                                                           
print $q->start_html(-title=>'MapServer - Dynamic Points', -bgcolor=>"#ffffff");                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                              
print "<form name=\"pointmap\" action=\"query_points.pl\" method=\"GET\">\n";                                                                                                                                                                                                                                                                                                                                 
print "<table border=\"1\" cellpadding=\"5\" cellspacing=\"2\">\n";                                                                                                                                                                                                                                                                                                                                           
print "<tr>\n";                                                                                                                                                                                                                                                                                                                                                                                               
print "<td>\n";                                                                                                                                                                                                                                                                                                                                                                                               
print "<input border=\"2\" type=\"image\" name=\"img\" src=\"$image_name\">\n";                                                                                                                                                                                                                                                                                                                               
print "</td>\n";                                                                                                                                                                                                                                                                                                                                                                                              
print "</tr>\n";                                                                                                                                                                                                                                                                                                                                                                                              
print "</table>\n";                                                                                                                                                                                                                                                                                                                                                                                           
print "</form>\n";                                                                                                                                                                                                                                                                                                                                                                                            
print "$msg<br>\n";                                                                                                                                                                                                                                                                                                                                                                                           
print "<a href=\"query_points.pl\"> Start over </a><br>\n";                                                                                                                                                                                                                                                                                                                                                   
print "<p><br><br><br></p>\n";                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                              
print $q->end_html();                                                                                                                                                                                                                                                                                                                                                                                         
# translate mouse click x,y into map longitude, latitude based on map extent. This is based on set_extent() in                                                                                                                                                                                                                                                                                                
# mapquakes.pl                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                              
sub get_click {                                                                                                                                                                                                                                                                                                                                                                                               
    my ($q, $map) = @_;                                                                                                                                                                                                                                                                                                                                                                                       
    my ($x, $y, $cx, $cy) = (0,0,0,0);                                                                                                                                                                                                                                                                                                                                                                        
    my $minx = $map->{extent}->{minx};                                                                                                                                                                                                                                                                                                                                                                        
    my $miny = $map->{extent}->{miny};                                                                                                                                                                                                                                                                                                                                                                        
    my $maxx = $map->{extent}->{maxx};                                                                                                                                                                                                                                                                                                                                                                        
    my $maxy = $map->{extent}->{maxy};                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                              
    if($q->param('img.x')) { # Make sure we got a click                                                                                                                                                                                                                                                                                                                                                       
        $x = $q->param('img.x');                                                                                                                                                                                                                                                                                                                                                                              
        $y = $q->param('img.y');                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                              
        $cx = ($maxx-$minx)/($map->{width}-1); # calculate cellsize in x and y                                                                                                                                                                                                                                                                                                                                
        $cy = ($maxy-$miny)/($map->{height}-1);                                                                                                                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                                                                                                                                              
        $x = $minx + $cx*$x; # change x,y from image to map coordinates                                                                                                                                                                                                                                                                                                                                       
        $y = $maxy - $cy*$y;                                                                                                                                                                                                                                                                                                                                                                                  
    }                                                                                                                                                                                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                                                                                                              
    return ($x, $y);                                                                                                                                                                                                                                                                                                                                                                                          
}                                                                                                                                                                                                                                                                                                                                                                                                             

= query_points.map =

MAP                                                                                                                                                                                                                                                                                                                                                                                                           
  STATUS ON                                                                                                                                                                                                                                                                                                                                                                                                   
  EXTENT -71.5 39.5 -63.0 46.0                                                                                                                                                                                                                                                                                                                                                                                
  SIZE 504 385                                                                                                                                                                                                                                                                                                                                                                                                
  IMAGETYPE PNG                                                                                                                                                                                                                                                                                                                                                                                               
  UNITS DD                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                              
SYMBOL                                                                                                                                                                                                                                                                                                                                                                                                        
  TYPE ELLIPSE                                                                                                                                                                                                                                                                                                                                                                                                
  NAME "circle"                                                                                                                                                                                                                                                                                                                                                                                               
  POINTS 1 1 END                                                                                                                                                                                                                                                                                                                                                                                              
  FILLED TRUE                                                                                                                                                                                                                                                                                                                                                                                                 
END                                                                                                                                                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                                                                                                                              
SYMBOL                                                                                                                                                                                                                                                                                                                                                                                                        
  TYPE VECTOR                                                                                                                                                                                                                                                                                                                                                                                                 
  NAME "plus"                                                                                                                                                                                                                                                                                                                                                                                                 
  POINTS .5 0 .5 1 -99 -99 0 .5 1 .5 END                                                                                                                                                                                                                                                                                                                                                                      
END                                                                                                                                                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                                                                                                                              
LAYER                                                                                                                                                                                                                                                                                                                                                                                                         
  NAME "points"                                                                                                                                                                                                                                                                                                                                                                                               
  TYPE POINT                                                                                                                                                                                                                                                                                                                                                                                                  
  STATUS ON                                                                                                                                                                                                                                                                                                                                                                                                   
  TOLERANCE 10                                                                                                                                                                                                                                                                                                                                                                                                
  # Need fake template for querys to work                                                                                                                                                                                                                                                                                                                                                                     
  TEMPLATE "bogus.html"                                                                                                                                                                                                                                                                                                                                                                                       
  CLASS                                                                                                                                                                                                                                                                                                                                                                                                       
    NAME "buoy"                                                                                                                                                                                                                                                                                                                                                                                               
    SYMBOL "circle"                                                                                                                                                                                                                                                                                                                                                                                           
    SIZE  8                                                                                                                                                                                                                                                                                                                                                                                                   
    COLOR 255 0 0                                                                                                                                                                                                                                                                                                                                                                                             
    OUTLINECOLOR 0 0 0                                                                                                                                                                                                                                                                                                                                                                                        
    LABEL                                                                                                                                                                                                                                                                                                                                                                                                     
      COLOR 255 0 0                                                                                                                                                                                                                                                                                                                                                                                           
      TYPE BITMAP                                                                                                                                                                                                                                                                                                                                                                                             
      SIZE MEDIUM                                                                                                                                                                                                                                                                                                                                                                                             
      POSITION AUTO                                                                                                                                                                                                                                                                                                                                                                                           
      PARTIALS FALSE                                                                                                                                                                                                                                                                                                                                                                                          
      BUFFER 2                                                                                                                                                                                                                                                                                                                                                                                                
    END # end of label                                                                                                                                                                                                                                                                                                                                                                                        
  END                                                                                                                                                                                                                                                                                                                                                                                                         
END                                                                                                                                                                                                                                                                                                                                                                                                           
LAYER                                                                                                                                                                                                                                                                                                                                                                                                         
  NAME "click"                                                                                                                                                                                                                                                                                                                                                                                                
  TYPE POINT                                                                                                                                                                                                                                                                                                                                                                                                  
  STATUS ON                                                                                                                                                                                                                                                                                                                                                                                                   
  CLASS                                                                                                                                                                                                                                                                                                                                                                                                       
    NAME "click"                                                                                                                                                                                                                                                                                                                                                                                              
    SYMBOL "plus"                                                                                                                                                                                                                                                                                                                                                                                             
    SIZE  6                                                                                                                                                                                                                                                                                                                                                                                                   
    COLOR 0 0 0                                                                                                                                                                                                                                                                                                                                                                                               
    LABEL                                                                                                                                                                                                                                                                                                                                                                                                     
      TYPE BITMAP                                                                                                                                                                                                                                                                                                                                                                                             
      SIZE TINY                                                                                                                                                                                                                                                                                                                                                                                               
      COLOR 0 0 0                                                                                                                                                                                                                                                                                                                                                                                             
      POSITION AUTO                                                                                                                                                                                                                                                                                                                                                                                           
      PARTIALS FALSE                                                                                                                                                                                                                                                                                                                                                                                          
      BUFFER 1                                                                                                                                                                                                                                                                                                                                                                                                
    END                                                                                                                                                                                                                                                                                                                                                                                                       
  END                                                                                                                                                                                                                                                                                                                                                                                                         
END                                                                                                                                                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                                                                                                                              
END                                                                                                                                                                                                                                                                                                                                                                                                           

back to PerlMapScript

Clone this wiki locally