[mapserver-users] custom programming with Mapserver's python or java or C# (OR perl) mapscript

Andy Colson andy at squeakycode.net
Mon Jan 6 07:32:48 PST 2014


On 1/6/2014 6:34 AM, Sajid Anwar wrote:
> Hello,
>
> I am wondering how to write a program (function) for Map server, which
> dynamically handle arbitrary shapefile, and will change the style like
> color etc, on the basis of attribute from shapefile. I want to develop
> and rendered choropleth map for arbitrary shapefile.
>
> I know that we can use MapScript languge like python for custom
> programming, and I already read some tutorial about python mapscript. I
> need help/direction about which scripting language is easy to use and
> more flexible and from where to start ,other link without Map-server
> website and example.
>
>
> I already use the Map file in cgi mode, but it is static and here we
> manually change the file(metadata) for each shape file. i am interested
> in a function /program which can handle styling for arbitrary shapefile.
>
>
> Thanks in advance
>
>
> sajid
>
> student
>

All languages are the same, and can do the same thing.  The question is 
not "which language is more flexable", but "which language do I know the 
best", or "what language would I enjoy learning for this project".

I choose Perl.  Not because of all the rave reviews it gets, or its 
massive popularity, but because I know perl, I love it, I think in it.

So pick a language that mapscript supports.  I can offer you the ideas I 
used to write my site, and you can implement them in any language.

I use mod_perl, FastCGI, and uwsgi... all of which are pretty similar.

I start out with a url like:
http://maps.camavision.com/map/iowacityia

I pull off the last word and stuff that into $xmap.
Then I check the url for ether WMS or info, and if not found, I return a 
suitable index.html file:

my $filename = MAPPATH."/$xmap.map";
my $map = new mapscript::mapObj($filename);

MAPPATH is outside the htdocs folder.

Then, I've had reports where people have huge monitors so I need to make 
sure the maxsize if at least 4096.  I didnt want to check all my .map 
files, so I just check in mapscript:

	if ($map->{maxsize} < 4096)
	{
		$map->{maxsize} = 4096;
	}

I load various values from the map file, like the bounding box:
	my $bbox = $map->{extent};
	$vars{'minx'} = $bbox->{minx};
	$vars{'miny'} = $bbox->{miny};
	$vars{'maxx'} = $bbox->{maxx};
	$vars{'maxy'} = $bbox->{maxy};

I generate some javascript for the index.html page:
	$zoom = "var bb = new  OpenLayers.Bounds.fromArray([$vars{'minx'}, 
$vars{'miny'}, $vars{'maxx'}, $vars{'maxy'}]);\n"
	. "\t\t\tmap.zoomToExtent(bb, true);\n";

And then I send it to the browser:
   my $index = $config{$xmap}->{'index'} // 'index.html';
   showTemplate($index, \%vars);

This page will include the openlayers stuff and setup to render the map. 
  openlayers will turn around and request map images using the url param 
WMS.

My code, when it sees a WMS requst does this:

	$owreq = new mapscript::OWSRequest();
	my @par = $web->paramNames();
	for my $x (@par)
	{
		my $v = $web->param($x);
		$owreq->setParameter($x, $v);
	}
	my $map = new mapscript::mapObj( MAPPATH."/$xmap.map" );

It creates a request object, and copies all the url params into the owreq.

And here is the part you will like.  If you pass along a parcel number:
http://maps.camavision.com/map/iowacityia?pin=1004178001

It dynamically creates a layer called annotate_pin (which is the blue 
highlight):

	if ($layername =~ 'annotate_pin')
	{
		# did we get a click point?
		my $cx = $web->param('LON');
		my $cy = $web->param('LAT');
		if ( defined($cx) && defined($cy))
		{
			$xpin = getPin($cx, $cy);
		}

		$q = $db->prepare("select shapeid from $xmap.getpoint where pin = \$1");
		$q->execute($xpin);

		my $layer = $map->getLayerByName('parcels');
		$layer->open();
		my $newlayer = $map->getLayerByName('annotate_pin');
		$newlayer->{status} = $mapscript::MS_ON;

		my $shp;
		($sid) = $q->fetchrow_array;
		if (defined($sid))
		{
			$shp = $layer->getShape(new mapscript::resultObj($sid));

		}
		$q = undef;
		$layer->close();
		my $shape = $shp->clone();
		$newlayer->addFeature($shape);
	}

In the .map file, the layer annotate_pin exists, but is mostly empty. 
It only contains a STYLE for drawing, but no data.  I find the shape 
from the parcels layer, clone it (just that one parcel) and add it to 
the annotate_pin layer.

This code is not the exact code I run.  I striped out a bunch to try and 
make it more readable.  On click of another parcel it sends an info url, 
which does almost the exact same thing to move the highlight.

Also, you can see I'm doing queries to PostGIS and not using mapserver's 
query's.

Hopefully this'll get you a start, although not exactly what you are 
looking for.

I'm happy to answer questions.

-Andy


More information about the mapserver-users mailing list