Skip to content
Permalink
Browse files
GRID layer: fix label positionning when requesting WGS84 graticule in…
… 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 fc36c0aa8b0277ae10770a6c959ad25927c5306b
Show file tree
Hide file tree
Showing 5 changed files with 195 additions and 11 deletions.
@@ -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);
@@ -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
@@ -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;
}

@@ -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;
}

@@ -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;
@@ -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;
}

@@ -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;
}

@@ -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;
@@ -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) {
@@ -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;
@@ -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 ) {
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.
@@ -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.