Opened 21 years ago

Closed 21 years ago

#301 closed defect (fixed)

Projections without inverse crash MapServer

Reported by: jhart@… Owned by: warmerdam
Priority: high Milestone:
Component: MapServer CGI Version: 4.0
Severity: normal Keywords:
Cc:

Description

MapServer crashes when trying to render a map in a projection that doesn't
support inverse projection. See posting in mapserver-users mar 26 2003

Jan Hartmann

Attachments (2)

bug_map.zip (200.5 KB ) - added by fwarmerdam 21 years ago.
Zip of .map and shapefile showing bug.
mapproject.c (12.9 KB ) - added by jhart@… 21 years ago.
hack to skip extent computation with non-invertable projection

Download all attachments as: .zip

Change History (8)

comment:1 by fwarmerdam, 21 years ago

Status: newassigned
Jan, 

please attach a minimal mapfile and shapefile to demonstrate the problem. 

Thanks,

by fwarmerdam, 21 years ago

Attachment: bug_map.zip added

Zip of .map and shapefile showing bug.

comment:2 by fwarmerdam, 21 years ago

Component: PROJ-PHP ModuleMapServer CGI
Resolution: fixed
Status: assignedclosed
This is in fact a crash in pj_transform() which didn't check if srcdefn->inv
was NULL before calling through it.  I have corrected pj_transform() to 
return an error, and then MapServer seems to fallback to using all the data
or something like that (it reports  "msProjectRect(): some points failed to
reproject, doing internal sampling." and seems to work OK). 

So, the fix is in PROJ (in CVS). 


comment:3 by fwarmerdam, 21 years ago

Resolution: fixed
Status: closedreopened
Jan Hartmann wrote:

>
> Did you see anything in your map? With me, MapServer returns OK now, but with
a blank map.
>
> Jan
>
>
> Frank Warmerdam wrote:
> This is in fact a crash in pj_transform() which didn't check if srcdefn->inv
> was NULL before calling through it.  I have corrected pj_transform() to
> return an error, and then MapServer seems to fallback to using all the data
> or something like that (it reports  "msProjectRect(): some points failed to
> reproject, doing internal sampling." and seems to work OK).


Jan,

Strangely, I get part of central africa and the area of indonesian to
borneo but that is all. (see attached).

I think the fact that this worked is a bit of a coincidence or a bug in
itself.

If you make some progress digging in msProjectRect() let me know.  I think
that msProjectRect() should really return MS_FALSE (perhaps it does) in
this case.

Best regards,
-- 
---------------------------------------+--------------------------------------
I set the clouds in motion - turn up   | Frank Warmerdam, warmerdam@pobox.com
light and sound - activate the windows | http://pobox.com/~warmerdam
and watch the world go round - Rush    | Geospatial Programmer for Rent

by jhart@…, 21 years ago

Attachment: mapproject.c added

hack to skip extent computation with non-invertable projection

comment:4 by fwarmerdam, 21 years ago

Hi Frank,

Some time ago we exchanged some mails on MapServer crashing when projecting to
projections that had no inverse projection, mostly
historical ones like Ortelius (see MapServer bug 301). I proposed a small
workaround that has been working without problem for me since then.

Is there a reason why this hack shouldn't be put into CVS? The reason I ask is
that I am going to publish in a few days my MUM presentation (MapClient, a DHTML
client for MapServer), together with code, User and Reference Guides and
examples. The examples are completely based on projections of a world map, the
easiest way of getting interesting maps without having to provide lots of data.
Until now I have used my own patched version of MapServer with all PROJ
projections. For public access, I need to use the official version and if that
one isn't patched I need to remove some twenty projections from the examples.
That is not a big deal, but I would like to have them all, especially since a
few of the remaining ones are famous Dutch ones .

Jan

comment:5 by fwarmerdam, 21 years ago

Jan, 

Sorry for not dealing with this sooner. 

I have stalled on it because I wanted to see if there was a better approach, 
and to try and understand what effects this might have in other conditions. 
I will spend a bit of time looking at it today and come up with some sort of
solution.

Best regards,

comment:6 by fwarmerdam, 21 years ago

Resolution: fixed
Status: reopenedclosed
OK, I have ended up changing msProjectRect() to look like this:

...
  /*
  ** If there have been any failures around the edges, then we had better
  ** try and fill in the interior to get a close bounds. 
  */
  if( failure > 0 )
  {
      failure = 0;
      for(x=rect->minx + dx; x<=rect->maxx; x+=dx) {
          for(y=rect->miny + dy; y<=rect->maxy; y+=dy) {
              prj_point.x = x;
              prj_point.y = y;
              msProjectGrowRect(in,out,&prj_rect,&rect_initialized,&prj_point,
                                &failure);
          }
      }

      if( !rect_initialized )
      {
          if( out == NULL || out->proj == NULL 
              || pj_is_latlong(in->proj) )
          {
              prj_rect.minx = -180;
              prj_rect.maxx = 180;
              prj_rect.miny = -90;
              prj_rect.maxy = 90;
          }
          else
          {
              prj_rect.minx = -22000000;
              prj_rect.maxx = 22000000;
              prj_rect.miny = -11000000;
              prj_rect.maxy = 11000000;
          }

          msDebug( "msProjectRect(): all points failed to reproject, trying to
fall back to using world bounds ... hope this helps.\n" );
      }
      else
      {
          msDebug( "msProjectRect(): some points failed to reproject, doing
internal sampling.\n" );
      }
  }

  rect->minx = prj_rect.minx;
  rect->miny = prj_rect.miny;
  rect->maxx = prj_rect.maxx;
  rect->maxy = prj_rect.maxy;

  if( !rect_initialized )
      return MS_FAILURE;
  else
      return(MS_SUCCESS);

The major issues are: 

 o We try to determine if the output coordinate system is lat/long or projected 
   in order to establish a somewhat more reasonable output bounds.  Of course,
   if it was projected in feet (for instance) the bounds would still not be
   right.  There are lots of ways in which the projected bounds could still 
   be too narrow. 

 o We still return MS_FALSE from the function if we fail.  Skimming the code
   calling msProjectRect() (there are lots of places!) it appears essentially
   nothing checks the return value.  Most calls to it turn around and use
   the rectangle with msWhichShapes() ... what we really should have is a way
   of selecting all shapes without passing a search rectangle for cases where
   this fails. 

 o There are lots of places msProjectRect() is used.  I am not at all convinced
   that using a "large" rectangle is going to be appropriate in all of them. 
   I think some are used to compute a rectangle for a WMS request to other
   servers for instance ... in which case the large rectangle may result in 
   hopelessly improperly sampled data.  In other cases, if the rectangle
   produced needs to be forward projected again, it may well be impossible since
   the bounds are outside the region of validity in many projections. 

However, on the whole this change should fix a bunch of cases Jan has identified
and not break anything that was working before.  Also, the modified debug
message should give some clue to users what is happening internally.


Note: See TracTickets for help on using tickets.