Skip to content

Commit

Permalink
GRID layer: fix label positionning when requesting WGS84 graticule in…
Browse files Browse the repository at this point in the history
… EPSG:3857

This clamps labels in the validity area of EPSG:3857, even if the eastings of the
BBOX exceed 20037508.
  • Loading branch information
rouault committed Feb 20, 2017
1 parent 094c6f5 commit fc36c0a
Show file tree
Hide file tree
Showing 5 changed files with 195 additions and 11 deletions.
131 changes: 120 additions & 11 deletions mapgraticule.c
Expand Up @@ -187,6 +187,19 @@ int msGraticuleLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery)
* These lines will be used when generating labels to get correct placement at arc/rect edge intersections.
*/
rectMapCoordinates = layer->map->extent;
#ifdef USE_PROJ
layer->project = msProjectionsDiffer(&(layer->projection), &(layer->map->projection));
if( layer->project &&
strstr(layer->map->projection.args[0], "epsg:3857") &&
pj_is_latlong(layer->projection.proj) )
{
if( rectMapCoordinates.minx < -20037508)
rectMapCoordinates.minx = -20037508;
if( rectMapCoordinates.maxx > 20037508 )
rectMapCoordinates.maxx = 20037508;
}
#endif

msFree(pInfo->pboundinglines);
pInfo->pboundinglines = (lineObj *) msSmallMalloc( sizeof( lineObj ) * 4 );
msFree(pInfo->pboundingpoints);
Expand All @@ -205,7 +218,6 @@ int msGraticuleLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery)
pInfo->pboundinglines[0].point[1].y = rectMapCoordinates.maxy;

#ifdef USE_PROJ
layer->project = msProjectionsDiffer(&(layer->projection), &(layer->map->projection));
if(layer->project)
msProjectLine(&layer->map->projection, &layer->projection, &pInfo->pboundinglines[0]);
#endif
Expand Down Expand Up @@ -287,7 +299,7 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape)
case 0:
if(!pInfo->blabelaxes) { /* Bottom */
pInfo->ilabelstate++;
shape->numlines = 0;
msFreeShape(shape);
return MS_SUCCESS;
}

Expand All @@ -306,15 +318,19 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape)

_FormatLabel( layer, shape, shape->line->point[0].x );
if(_AdjustLabelPosition( layer, shape, posBottom ) != MS_SUCCESS)
return MS_FAILURE;
{
msFreeShape(shape);
pInfo->ilabelstate++;
return MS_SUCCESS;
}

pInfo->ilabelstate++;
return MS_SUCCESS;

case 1:
if(!pInfo->blabelaxes) { /* Top */
pInfo->ilabelstate++;
shape->numlines = 0;
msFreeShape(shape);
return MS_SUCCESS;
}

Expand All @@ -333,7 +349,11 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape)

_FormatLabel( layer, shape, shape->line->point[0].x );
if(_AdjustLabelPosition( layer, shape, posTop ) != MS_SUCCESS)
return MS_FAILURE;
{
msFreeShape(shape);
pInfo->ilabelstate++;
return MS_SUCCESS;
}

pInfo->ilabelstate++;
return MS_SUCCESS;
Expand Down Expand Up @@ -372,7 +392,7 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape)
case 0:
if(!pInfo->blabelaxes) { /* Left side */
pInfo->ilabelstate++;
shape->numlines = 0;
msFreeShape(shape);
return MS_SUCCESS;
}

Expand All @@ -391,15 +411,19 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape)

_FormatLabel( layer, shape, shape->line->point[0].y );
if(_AdjustLabelPosition( layer, shape, posLeft ) != MS_SUCCESS)
return MS_FAILURE;
{
msFreeShape(shape);
pInfo->ilabelstate++;
return MS_SUCCESS;
}

pInfo->ilabelstate++;
return MS_SUCCESS;

case 1:
if(!pInfo->blabelaxes) { /* Right side */
pInfo->ilabelstate++;
shape->numlines = 0;
msFreeShape(shape);
return MS_SUCCESS;
}

Expand All @@ -418,7 +442,11 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape)

_FormatLabel( layer, shape, shape->line->point[0].y );
if(_AdjustLabelPosition( layer, shape, posRight ) != MS_SUCCESS)
return MS_FAILURE;
{
msFreeShape(shape);
pInfo->ilabelstate++;
return MS_SUCCESS;
}

pInfo->ilabelstate++;
return MS_SUCCESS;
Expand Down Expand Up @@ -1039,7 +1067,20 @@ static int _AdjustLabelPosition( layerObj *pLayer, shapeObj *pShape, msGraticule

#ifdef USE_PROJ
if(pLayer->project)
{
msProjectShape( &pLayer->projection, &pLayer->map->projection, pShape );

/* Poor man detection of reprojection failure */
if( pj_is_latlong(pLayer->projection.proj) !=
pj_is_latlong(pLayer->map->projection.proj) )
{
if( ptPoint.x == pShape->line->point[0].x &&
ptPoint.y == pShape->line->point[0].y )
{
return MS_FAILURE;
}
}
}
#endif

if(pLayer->transform) {
Expand Down Expand Up @@ -1067,8 +1108,8 @@ static int _AdjustLabelPosition( layerObj *pLayer, shapeObj *pShape, msGraticule
pShape->line->point[0].y = fabs(rectLabel.maxy - rectLabel.miny) * 2 + 5;
break;
case posLeft:
pShape->line->point[1].x = 0;
pShape->line->point[0].x = fabs(rectLabel.maxx - rectLabel.minx) * 2 + 5;
pShape->line->point[0].x = 0;
pShape->line->point[1].x = fabs(rectLabel.maxx - rectLabel.minx) * 2 + 5;
break;
case posRight:
pShape->line->point[1].x = pLayer->map->width;
Expand All @@ -1081,7 +1122,75 @@ static int _AdjustLabelPosition( layerObj *pLayer, shapeObj *pShape, msGraticule

#ifdef USE_PROJ
if(pLayer->project)
{
/* Clamp coordinates into the validity area of the projection, in the */
/* particular case of EPSG:3857 (WebMercator) to longlat reprojection */
if( strstr(pLayer->map->projection.args[0], "epsg:3857") &&
pj_is_latlong(pLayer->projection.proj) )
{
if( !pLayer->map->projection.gt.need_geotransform &&
ePosition == posLeft && pShape->line->point[0].x < -20037508)
{
pShape->line->point[1].x = -20037508 + (pShape->line->point[1].x -
pShape->line->point[0].x);
pShape->line->point[0].x = -20037508;
}
else if( pLayer->map->projection.gt.need_geotransform &&
ePosition == posLeft &&
pLayer->map->projection.gt.geotransform[0] +
pShape->line->point[0].x *
pLayer->map->projection.gt.geotransform[1] +
pShape->line->point[0].y *
pLayer->map->projection.gt.geotransform[2] < -20037508)
{
double y_tmp;
double width = pShape->line->point[1].x - pShape->line->point[0].x;

y_tmp = pLayer->map->projection.gt.geotransform[3] +
pShape->line->point[0].x *
pLayer->map->projection.gt.geotransform[4] +
pShape->line->point[0].y *
pLayer->map->projection.gt.geotransform[5];
pShape->line->point[0].x =
pLayer->map->projection.gt.invgeotransform[0] +
-20037508 * pLayer->map->projection.gt.invgeotransform[1] +
y_tmp * pLayer->map->projection.gt.invgeotransform[2];
pShape->line->point[1].x = pShape->line->point[0].x + width;
}

if( !pLayer->map->projection.gt.need_geotransform &&
ePosition == posRight && pShape->line->point[1].x > 20037508)
{
pShape->line->point[0].x = 20037508 - (pShape->line->point[1].x -
pShape->line->point[0].x);
pShape->line->point[1].x = 20037508;
}
else if( pLayer->map->projection.gt.need_geotransform &&
ePosition == posRight &&
pLayer->map->projection.gt.geotransform[0] +
pShape->line->point[1].x *
pLayer->map->projection.gt.geotransform[1] +
pShape->line->point[1].y *
pLayer->map->projection.gt.geotransform[2] > 20037508)
{
double y_tmp;
double width = pShape->line->point[1].x - pShape->line->point[0].x;

y_tmp = pLayer->map->projection.gt.geotransform[3] +
pShape->line->point[1].x *
pLayer->map->projection.gt.geotransform[4] +
pShape->line->point[1].y *
pLayer->map->projection.gt.geotransform[5];
pShape->line->point[1].x =
pLayer->map->projection.gt.invgeotransform[0] +
20037508 * pLayer->map->projection.gt.invgeotransform[1] +
y_tmp * pLayer->map->projection.gt.invgeotransform[2];
pShape->line->point[0].x = pShape->line->point[1].x - width;
}
}

msProjectShape( &pLayer->map->projection, &pLayer->projection, pShape );
}
#endif

switch( ePosition ) {
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
75 changes: 75 additions & 0 deletions msautotest/wxs/wms_grid_reproj_to_3857.map
@@ -0,0 +1,75 @@
#
# Test WMS
#
# REQUIRES: INPUT=GDAL OUTPUT=PNG SUPPORTS=WMS
#
# Check that labels are in the left and right
#
# RUN_PARMS: wms_grid_reproj_to_3857_square_pixels_within_validity.png [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&FORMAT=image/png&TRANSPARENT=false&LAYERS=grid4326&CRS=EPSG:3857&STYLES=&WIDTH=2000&HEIGHT=1500&BBOX=-20000000,-15000000,20000000,15000000" > [RESULT_DEMIME]
#
# RUN_PARMS: wms_grid_reproj_to_3857_square_pixels_beyond_validity.png [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&FORMAT=image/png&TRANSPARENT=false&LAYERS=grid4326&CRS=EPSG:3857&STYLES=&WIDTH=2036&HEIGHT=739&BBOX=-39996745.16861447,-14460662.759102784,39683659.10075838,14460662.759102784" > [RESULT_DEMIME]
#
# RUN_PARMS: wms_grid_reproj_to_3857_non_square_pixels_beyond_validity.png [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&FORMAT=image/png&TRANSPARENT=false&LAYERS=grid4326&CRS=EPSG:3857&STYLES=&WIDTH=2036&HEIGHT=735&BBOX=-39996745.16861447,-14460662.759102784,39683659.10075838,14460662.759102784" > [RESULT_DEMIME]
#

MAP
NAME WMS_GRID_TEST
EXTENT -180 -90 180 90
UNITS DD
FONTSET "../misc/fonts.lst"

WEB
METADATA
wms_enable_request "*"
END
END

PROJECTION
"init=epsg:4326"
END

OUTPUTFORMAT
NAME GDPNG
DRIVER "GD/PNG"
MIMETYPE "image/png"
EXTENSION "png"
END

LAYER
NAME "grid4326"

METADATA
"wms_srs" "EPSG:4326 EPSG:3857"
"wms_extent" "-180 -90 180 90"
END

TYPE LINE

CLASS
NAME "Graticule"
COLOR 255 153 0
LABEL
COLOR 0 0 0
FONT lucida
TYPE truetype
SIZE 8
POSITION AUTO
PARTIALS FALSE
BUFFER 5
OUTLINECOLOR 255 255 255
END
END

PROJECTION
"init=epsg:4326"
END

GRID
LABELFORMAT 'DDMMSS' # nice if a projected SRS used
MININTERVAL 30
MAXINTERVAL 30
END

END # Layer

END

0 comments on commit fc36c0a

Please sign in to comment.