MapServer / MapServer-import

3 stars 2 forks source link

Make Reference Map extents available through CGI template #1102

Open tbonfort opened 12 years ago

tbonfort commented 12 years ago

Reporter: jdoyon@nrcan.gc.ca Date: 2004/12/02 - 19:20

I've been working on client-side JavaScript/DHTML mapping lately.

I now have an interface that does everything I need talking directly to the
MapServer CGI, without going through any form of application server (Zope in my
case).

I would like to make it possible to pan around the map using the reference map,
but this is impossible at this time because there is no way to get the reference
map's extent from a CGI template.

I've already modified my own maptemplate.c in 4.4.0 and this works fine ...

Here's the code (Place in processLine() somewhere):

  // Allow access to the reference map extents if it is on.
  if (msObj->Map->reference.status == MS_ON) {
    sprintf(repstr, "%f", msObj->Map->reference.extent.minx); // Individual
reference map extent elements for spatial query building
    outstr = gsub(outstr, "[refminx]", repstr);
    sprintf(repstr, "%f", msObj->Map->reference.extent.maxx);
    outstr = gsub(outstr, "[refmaxx]", repstr);
    sprintf(repstr, "%f", msObj->Map->reference.extent.miny);
    outstr = gsub(outstr, "[refminy]", repstr);
    sprintf(repstr, "%f", msObj->Map->reference.extent.maxy);
    outstr = gsub(outstr, "[refmaxy]", repstr);
    sprintf(repstr, "%f %f %f %f", msObj->Map->reference.extent.minx,
msObj->Map->reference.extent.miny, msObj->Map->reference.extent.maxx,
msObj->Map->reference.extent.maxy);
    outstr = gsub(outstr, "[refext]", repstr);
  }

I'd like to submit this for inclusion in future versions of MapServer!

Thanks,
J.F.
tbonfort commented 12 years ago

Author: jdoyon@nrcan.gc.ca Date: 2004/12/02 - 19:29

Oh and I forgot, should probably add the _esc version of the [refext] tag, so
here's a new version of the complete code:

  // Allow access to the reference map extents if it is on.
  if (msObj->Map->reference.status == MS_ON) {
    sprintf(repstr, "%f", msObj->Map->reference.extent.minx); // Individual
reference map extent elements for spatial query building
    outstr = gsub(outstr, "[refminx]", repstr);
    sprintf(repstr, "%f", msObj->Map->reference.extent.maxx);
    outstr = gsub(outstr, "[refmaxx]", repstr);
    sprintf(repstr, "%f", msObj->Map->reference.extent.miny);
    outstr = gsub(outstr, "[refminy]", repstr);
    sprintf(repstr, "%f", msObj->Map->reference.extent.maxy);
    outstr = gsub(outstr, "[refmaxy]", repstr);
    sprintf(repstr, "%f %f %f %f", msObj->Map->reference.extent.minx,
msObj->Map->reference.extent.miny, msObj->Map->reference.extent.maxx,
msObj->Map->reference.extent.maxy);
    outstr = gsub(outstr, "[refext]", repstr);
    encodedstr =  msEncodeUrl(repstr);
    outstr = gsub(outstr, "[refext_esc]", encodedstr);
    free(encodedstr);
  }

Cheers,
J.F.
tbonfort commented 12 years ago

Author: sdlime Date: 2004/12/02 - 19:40

Tom: Panning via a reference map has long been a feature of MapServer. Because 
a reference map is fixed in extent it's not necessary to pass it. Just call the 
input element with the reference map in it "ref" and it should work. The normal 
Itasca demo does this, and the DHTML LandView application:

  http://www.dnr.state.mn.us/maps/landview_dhtml_x.html?layers=dlgstln2+lakes

Does this too. Just goes to the CGI for necessary components, including a 
reference map. I do have to seed the component with the reference map extent. 
Is that what you're using the template values for? In that case I see the value 
in the new substitution strings.

Steve
tbonfort commented 12 years ago

Author: sdlime Date: 2004/12/02 - 19:46

Fixed in 4.5. Also added [refext_esc] tag support for consistency.

Steve
tbonfort commented 12 years ago

Author: jdoyon@nrcan.gc.ca Date: 2004/12/02 - 19:58

"Tom:"

I assume you mean J.F. ?? :)

OK, I should elaborate on what i'm doing.  I've created a Web Mapping Interface
that talks directly to the MapServer CGI, WITHOUT refreshing the page.

What I do is I setup an invisible IFrame that talks to the CGI "in the
background".  The Mapserver template is a basic HTML layout with all the
variables I want:

<html>
<head>
<title>MapServer Key-Value Pairs</title>
</head>
<body onLoad="parent.window.ami_refreshMap();">
<table id="ami_kvp_table">
  <tr><td>map</td><td>[map]</td></tr>
  <tr><td>scalebar</td><td>[scalebar]</td></tr>
  <tr><td>mapext</td><td>[mapext]</td></tr>
  <tr><td>mapsize</td><td>[mapsize]</td></tr>
  <tr><td>image</td><td>[img]</td></tr>
  <tr><td>scale</td><td>[scale]</td></tr>
  <tr><td>mapwidth</td><td>[mapwidth]</td></tr>
  <tr><td>ref</td><td>[ref]</td></tr>
  <tr><td>mapheight</td><td>[mapheight]</td></tr>
  <tr><td>center_x</td><td>[center_x]</td></tr>
  <tr><td>center_y</td><td>[center_y]</td></tr>
  <tr><td>zoom_0</td><td>[web_zoom0]</td></tr>
  <tr><td>zoom_1</td><td>[web_zoom1]</td></tr>
  <tr><td>zoom_2</td><td>[web_zoom2]</td></tr>
  <tr><td>zoom_3</td><td>[web_zoom3]</td></tr>
  <tr><td>zoom_4</td><td>[web_zoom4]</td></tr>
  <tr><td>zoom_5</td><td>[web_zoom5]</td></tr>
  <tr><td>zoom_6</td><td>[web_zoom6]</td></tr>
  <tr><td>zoom_7</td><td>[web_zoom7]</td></tr>
  <tr><td>zoom_8</td><td>[web_zoom8]</td></tr>
  <tr><td>zoom_9</td><td>[web_zoom9]</td></tr>
  <tr><td>layerlist</td><td>[layers]</td></tr>
  <tr><td>zoomto</td><td>[web_listzoomto]</td></tr>
  <tr><td>refext</td><td>[refext]</td></tr>
</table>
<div id="ami_innerhtml_point">
<table border="0" cellspacing="0" cellpadding="3" width="100%" bgcolor="#FFFFFF"
id="ami_legend_table">
[legend]
</table>
</div>
</body>
</html>

Using this technique, I can basically do very nice interfaces without any
mapscript or other server side code, so long as the CGI has all the features I
need.  Because the IFrame is a document, I can look through it using DOM as
required, and load different URL's into it.  The Javascript code simply
dynamically writes Mapserver CGI URL's, with the IFrame as a target.

In my case, one mapping interface might have many maps, with many reference maps
of different extents, sizes, etc ... Therefore I cannot make assumptions about
it in the page itself, so I need to read it from what mapserver returns.

Based on this paradigm, I may need access to other variables as well in the
future.  I can imagine other approaches that would have the same requirements
(Java client applets?), so I figured this might be useful in the core MapServer
(I'd really rather not fork a local source tree for this!).  Also you never
know, someone might want to display the values on a web page someday?

I'll try to get my demo out the firewall so you can look at it, it'll all make
sense then :)
tbonfort commented 12 years ago

Author: sdlime Date: 2004/12/02 - 20:34

J.F (Sorry about the Tom, I got it right in the source code attribution 
though!): Sounds cool, I'd love to see it when you're finished. The LandView 
example is working in a similar fashion. There is never a page refresh, just 
component refreshes. I use javascript to manage all the coordinate 
computations, and to retrieve new components as necessary. The legend container 
uses a straight html legend and new versions are retrieved as necessary. You 
add layers or change groupings via your mapfile. Ultimately you could have a 
generic DHTML interface that would take all it's configuration from a mapfile.

Steve
tbonfort commented 12 years ago

Author: sdlime Date: 2004/12/02 - 21:02

Oh, one other thing. Note than you can create XML templates which may make DOM 
parsing a bit easier. I've done this before when passing information back to a 
java application. 

Steve
tbonfort commented 12 years ago

Author: jdoyon@nrcan.gc.ca Date: 2004/12/03 - 21:00

Steve,

OK, well then I guess this request makes sense :) I may have more of this type
in the future, based on similar requirements ...

The XML thing, althugh doable, is more painful since you need browser dependent
technologies that work quite differently.  This is why I chose to use HTML, for
cross-browser support it's MUCH easier.  If you ever want to use XML parsing in
the client, there's the Sarissa library which seems to be most useful:
https://sourceforge.net/projects/sarissa.

On this topic: Woud there be a simple way to dump *ALL* variables relevant to
rendering a map and it's components to the client? something like
"mode=vardump", that could return everything as HTML or XML, or maybe using a
templating system based on the HTML legend functionality.

Maybe you could introspect the Map object and dump all it's variables, or
something like that ... The kind of feature you write once and never have to
wrry about again because it's smart enough to grow with the software.  In OO
this would be easy to do :)

Anyways, I know it's a bit out there, but it's an idea ... With smarter and
smarter clients,, it may become useful to a wider audience at some point ...

Cheers,
J.F.