Opened 20 years ago

Last modified 16 years ago

#980 reopened enhancement

Layer conditional on some other layer(s) being drawn

Reported by: woodbri@… Owned by: sdlime
Priority: high Milestone: 5.6 release
Component: MapServer C Library Version: unspecified
Severity: minor Keywords:
Cc:

Description (last modified by sdlime)

I would like to be able to draw a layer, BUT only if some other layer(s) got
drawn. The purpose for this is to be able to generate conditional copyrights on
the map.

Here is the scenario, I have multiple vendor data sets all pulled together into
a mapfile, but depending on scale and location I might only render data from
some of the vendor data. Then as the last layers being drawn are the copyrights,
I only want to place the copyrights required based on the data that was actually
rendered.

I'm thinking of a mechanism like:

LAYER
  NAME "abc"
  SET_IF_DRAWN vendor1 1
  ...
END
LAYER
  NAME "xyz"
  SET_IF_DRAWN vendor2 1
  ...
END
...
LAYER
  NAME "copyright1"
  STATUS OFF
  IF vendor1 and not vendor2 STATUS ON
  ...
END
LAYER
  NAME "copyright2"
  STATUS OFF
  IF vendor2 and not vendor1 STATUS ON
  ...
END
LAYER
  NAME "copyright3"
  STATUS OFF
  IF vendor1 and vendor2 STATUS ON
  ...
END

-- OR --

LAYER
  NAME "copyright"
  STATUS DEFAULT
  ...
  IF vendor1 and not vendor2 TEXT "bla bla bla 1"
  IF vendor2 and not vendor1 TEXT "bla bla bla 2"
  IF vendor1 and vendor2 TEXT " bla bla bla 1 and 2"
  ...
END

I think that there are probably other good uses of this besides the example
above. The key to this is that the variable only gets set if data is actually
rendered into the image. If later layer obliterates what was drawn, that can be
ignored and the variable would stay set.

Change History (7)

comment:1 by sdlime, 20 years ago

Resolution: wontfix
Status: newclosed
Steve: This is already supported, although via another mechanism. Checkout the 
REQUIRES and LABELREQUIRES parameters. You can write expressions that do 
basically what you're asking. E.g.

LAYER
  NAME 'LANDSAT'
  ...
END

LAYER
  NAME 'LANDSAT_COPYRIGHT'
  REQUIRES '[LANDSAT]'
  ...
END

A simple example that would easier to achieve using GROUPs but you get the 
idea. The expressions can contain references to multiple layers with and|or 
logical operators. There is also a sepecial tag called [raster] that will be 
true if any raster layers are on and false otherwise. The tags contain layer 
names and perhaps even group names (it's been awhile so I'd have to check the 
docs or even source). I've used these a way to trigger alternative 
presentations of layers depending on the presence or absence of raster 
backgrounds. For example, turn off vector lakes if USGS DLGs are visible. 
There are some limitations, for example, the expression is evaluated at the 
time a the layer is rendered. If the conditional is based on a layer yet to be 
renedered it could be wrong because that following layer may also have a 
REQUIRES statement. If you stick with testing against layers that have been 
already processed then all will be well. At least in the scenario you paint it 
will work just fine. Marking as WONTFIX for the moment.

Steve

comment:2 by woodbri@…, 19 years ago

Resolution: wontfix
Status: closedreopened
Steve, Thanks this looks good, and I finally got around to trying it out. I'm
reopening this because it does not seem to support groups only layer names. This
is somewhat problemmatic for the application described as I will have to put 25+
layer names in my REQUIRES statement which seems a little crazy. And it makes
maintenance a problem and I'm hoping that I can have that many terms in an
expression :)

For my purpose if you used a group name then I would like it to be true if any
layer in the group was rendered.

Also, with a little experimentation it seems that there is a problem with this
code (in MS 4.0.1) where

REQUIRES "[navteq]"
REQUIRES "[navteq]|1"
REQUIRES "![navteq]"
REQUIRES "![navteq]|1"

ALL are FALSE if there is no layer named 'navteq', I found this out because I
have GROUP "navteq" in all my Navteq layers.

REQUIRES "1|[navteq]"
REQUIRES "1|![navteq]"

both eval to TRUE, which I kind of expected, but it seems that if you eval a
term to undefined it aborts the evaluation process. I think it would be better
if all undefined terms were evaluated to FALSE.

comment:3 by woodbri@…, 19 years ago

An additional observation/problem is that it seems the the status of the LAYERS
in the requires statement does NOT reflect if the layer was rendered or not. For
example, all my layers in the mapfile are STATUS DEFAULT and rendering is
controlled via the MINSCALE/MAXSCALE settings. So in my mapfile I have:

generalized public layers like vmap0 MINSCALE 4,000,000
then Tiger for the US  MAXSCALE 4,000,000
and  Navteq for Canada MAXSCALE 4,000,000

If I am at SCALE 20,000,000 the navteq layers are still TRUE. This is even so if
I am outside the extents of the Navteq data.

comment:4 by sdlime, 19 years ago

Scale should be taken into account. The code looks at each layer and determines 
if it is to be rendered. Those values are then used in the requires expression. 
I'll look into it though. Can you confirm the MapServer version? This was 
broken big time prior to 4.4.

Steve

comment:5 by woodbri@…, 19 years ago

All the testing I just did was on 4.0.1, I don't have 4.4 installed anywhere and
can't get to it until sometime in Jan. with my current deadlines. I just want to
make sure these issues, if they still are issues, get addressed. It should be
pretty easy for you to reproduce my tests above. Just use [asdf] if that name
does not exist, and also try it with a group.

Thank you for checking into this.

comment:6 by sdlime, 19 years ago

The group issue is still there in 4.4 and is not trivial to solve. The scale 
issues are how I found the problems in the first place and have been fixed in 
the 4.4 release.

Steve

comment:7 by sdlime, 16 years ago

Description: modified (diff)
Milestone: 5.4 release
Note: See TracTickets for help on using tickets.