mapserver and msCross

Rodrigo Martín LÓPEZ GREGORIO rodrigomartin at LOPEZGREGORIO.COM.AR
Mon Jun 11 16:31:24 EDT 2007


Hi Mark. A few month ago (Jan 22) Stefan Schwarzer ask a similar question
and in that moment I send him my response outside the list. I paste here my
last mail to him in wich I put a long explanation about all the steps I had
to do to use PHP Mapscript with mscross. I dont even remember what I wrote
but I paste it here. If you have any question ask me again. Sorry my
english. Rodrigo.

Hi. Ok, lets see if with some examples I can show you what I was talking
about previously. Sorry if sometimes I ask basics questions or explain some
basic stuff but I allways try to explain in a way that even my mother can
understand what I'm talking about.

First of all, if you play around a little bit with the mscross code, you
will see that the way mscross obtains the image of the map is asking
directly to mapserver cgi interface, generating the necesary url and
assigning it to an <img> HTML element (created dinamically by de javascript
code). So, what ajax interface was expecting from the server is an image
file and not an HTML file. That is why you must modify your PHP Mapscript
file to return an image file instead of just HTML code.

So, lets go with a simple example... To make it simple, supose you have a
mapfile ready to use with mapserver and do not need to create anything
dinamically so the PHP Mapscript becomes quite simple. Lets supose the
mapfile have a png OUTPUTFORMAT, and three LAYERS named "countrys" "rivers"
and "sea". If the mapfile is located in /mymaps/ and it name is "
example1.map", then the CGI url to obtain a map (the one generated by
mscross) is something like this:

http://myserver/cgi-bin/mapserv.exe?
map=/mymaps/example1.map&mode=map&mapext=5649512+6099485+5711778+6144474&mapsize=800+600&
layers=countrys%20rivers%20sea

(note that I'm using mapserver for windows but on linux the url will be
almost the same)

The "object" returned by mapserver CGI interface will be an Image object (
i.e. the content of the image).

So the first thing you need to use your PHPMapscript with the mscross
interface is make that your PHP Mapscript file return an image object and
not a html object with an <img> element on it. So, lets see the contest of
this simple PHP Mapscript file:

<?php
header("Content-type: image/png");
//Before we send any data to the browser we set the header "Content-type"
//of the response to "image/png" so the browser interprets the content of
the response as a png image file.

$map = ms_newMapObj("/mymaps/example1.map");
// We create the map object based on the example1.map file as template

$map->setExtent(5649512,6099485,5711778,6144474);
// We set the extent of map

$map->setSize(800,600);
// and set the image size (resolution)

$map->getLayerByName("countrys")->set(status,MS_ON);
$map->getLayerByName("rivers")->set(status,MS_ON);
$map->getLayerByName("sea")->set(status,MS_ON);
// Set the status of three layers to on

$image=$map->draw();
$imagename=$image->saveWebImage();
//Draw the image to a temp file and copy image name to the $imagename
variable

$image = ImageCreateFromPng("/ms4w/tmp/".$imagename);
// Read the image saved previously to the $image variable

imagePng($image);
// Return the image content to the browser
?>

Maybe there is a way to avoid the save to disk and read from disk operation
but I didn't waste too much time looking for an alternative. So the previous
PHP Mapscript will create a mapobject, set the properties properly and then
return the image to the browser just like an image object.

If you call this php file from your browser, the browser will get a png
image file with the map drawed. Obviously the PHP Mapscript could be more
complex, create layers, class and labels dinamically, but it must be always
return an image file which is achieved with the header function in conjunct
with the imagePng call at the end of the Mapscript.

The next thing to do is make this Mapscript more flexible, so it could
recieve the map extent, map size and layers (and maybe the mapfile even) as
parameters. Sinse mscross use the GET method to obtain images we can modify
our Mapscript file to get this parameters and set it properly. So, if we
mantain the variables name as the ones used to get images from CGI interface
to make it more simple we can modify our PHP Mapscript file so it can be
more flexible and modify its output according to the url parameters:

<?php
header("Content-type: image/png");

$map = ms_newMapObj($_GET['map']);
// We create the map object based on the mapfile received as parameter

$extent = explode(" ",$_GET['mapext']);
$map->setExtent($extent[0], $extent[1], $extent[2], $extent[3]);
// We get the mapext parameter... split it on its 4 parts using the space
character as splitter

$size = explode(" ",$_GET['mapsize']);
$map->setSize($size[0], $size[1]);
// and set the image size (resolution) based on mapsize parameter

$layerslist=$_GET['layers'];
for ($layer = 0; $layer < $map->numlayers; $layer++) {
    $lay = $map->getLayer($layer);
    if ((strpos($layerslist,($map->getLayer($layer)->name)) !== false) or
(($map->getLayer($layer)->group != "") and
(strpos($layerslist,($map->getLayer($layer)->group)) !== false))){
// if the name property of actual $lay object is in $layerslist
// or the group property is in $layerslist then the layer was requested
//so we set the status ON... otherwise we set the stat to OFF
        $lay->set(status,MS_ON);
    } else {
        $lay->set(status,MS_OFF);
    }
}

// The next lines are the same as previous mapscript
$image=$map->draw();
$imagename=$image->saveWebImage();
$image = ImageCreateFromPng("/ms4w/tmp/".$imagename);
imagePng($image);
?>

If you want to get a map drawed throw this mapscript, you must now pass
various parameters in the url... something like this:

http://myserver/myPHPMapscript.php?map=/mymaps/example1.map&mapext=5649512+6099485+5711778+6144474&mapsize=800+600&layers=countrys%20rivers%20sea

Again, the Mapscript could be more complex but always must return an image
object.

So the last thing we must do is get it work with the mscross ajax... Lets
work with the last version of mscross javascript available at:
http://datacrossing.crs4.it/download.php?l=en&id=mscross-1.1.8.js

First take a look at the get_map_url() method of mscross class on
mscross-1.1.8.js file... It looks something like this (I remove some lines
which gives support to use wms servers):

  this.get_map_url = function()
  {
    var my_url;

    if (_protocol == 'mapservercgi')
    {
      var size = 'mapsize=' + (_map_w+_map_w_bord+_map_w_bord) + '+'
                            + (_map_h+_map_h_bord+_map_h_bord);
      var ext  = 'mapext=' + (_ext_Xmin-i.wPixel2real(_map_w_bord)) + '+'
                           + (_ext_Ymin-i.hPixel2real(_map_h_bord)) + '+'
                           + (_ext_Xmax+i.wPixel2real(_map_w_bord)) + '+'
                           + (_ext_Ymax+i.hPixel2real(_map_h_bord)) ;

      my_url = _cgi + '?mode=' + _mode + '&' + _map_file + '&' +
               ext + '&' + size + '&layers=' + _layers;

      // Opera9 Bug Fix (onload event don't work if image is in cache)
      if (browser.isOP ) {my_url = my_url + '&' + Math.random();}
    }

    return my_url + '&' + _args;
  }

Basically, this function build the url of the Mapserver CGI interface, so we
must get it work with our recently created PHP Mapscript file. If you take a
look at the line in bold, there is where the url is created:
my_url = _cgi + '?mode=' + _mode + '&' + _map_file + '&' + ext + '&' + size
+ '&layers=' + _layers;

there are some fixed (strings) parts and some variable parts in this line...
first it put the _cgi content which is set using the mscross setCgi()
method. Then it add the mode parameter that we dont need to use so it could
be removed. Then the mapfile parameter which is set using the mscross
setMapFile() method. afther mapfile parameter it puts the extent parameter
at ext variable which is created some lines before and is based on the
mscross object properties setted by the setFullExtent() method and the size
parameter (width and height of image) which are calculated on the mscross
object creation from container div width and height. Finaly it pass the
layers parameter based on _layers variable setted by the mscross setLayers()
method.

So we want to get this url look like the one we create for the second PHP
Mapscript file, so we need to set the variables properly to get my_url look
like:

http://myserver/myPHPMapscript.php?map=/mymaps/example1.map&mapext=5649512+6099485+5711778+6144474&mapsize=800+600&
layers=countrys%20rivers%20sea

The way to obtain this is:
set the _cgi variable to "http://myserver/myPHPMapscript.php" using the
setCgi() method.
set the mapfile to "/mymaps/example1.map" using the setMapFile() method.
set map extentention to (5649512,6099485,5711778,6144474) using the
setFullExtent() method.
and set the layers to "countrys rivers sea" using the setLayers() method
(the map size is setted automatically when the mscross object is created).
and finally if yo want to avoid the pass of mode parameter you can modify
the get_map_url() method and remove it from the line as follows:

my_url = _cgi + '?' + _map_file + '&' + ext + '&' + size + '&layers=' +
_layers;

So, at this point we can make a simple html file to get our mscross and PHP
Mapscript working together... a simple html could be the next one:

<html>
<script src="mscross-1.1.8.js" type="text/javascript"></script>
<body>
<div id="map_tag" style="position:absolute; top:10px; left:10px; width:
800px; height: 600px; border-width:1px; border-color:#000088;
border-style:solid;"></div>
</body>
<script type="text/javascript">
myMap = new msMap(document.getElementById('map_tag'),' ');
myMap.setCgi( 'http://myserver/myPHPMapscript.php ' );
myMap.setFullExtent( 5649512,5711778,6099485);
myMap.setMapFile( '/mymaps/example1.map' );
myMap.setLayers('countrys rivers sea');
myMap.redraw();
</script>
</html>

Ok, I think that this is all :P. I hope I was clear enough but I encourage
you to ask me whatever you want. Sorry my veeeeeery long mail and I hope
that it be helpful.

Greetings from Argentina.

On 6/11/07, Mark Brooks <mark_brooks at ncsu.edu> wrote:
>
> I'm trying to implement msCross (ajax) ith mapserver and mapscript
> (PHP).  My maps are dynamic and are usually created on-the-fly based on
> user input.  Therefore, much of my code is PHP using mapscript.
>
> Does anyone have any examples I can see that demonstrate the integration
> of msCross with mapscript?
>
> Much thanks,
> Mark
> NC State University
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.osgeo.org/pipermail/mapserver-users/attachments/20070611/bddc53eb/attachment.html


More information about the mapserver-users mailing list