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