Skip to content

Commit

Permalink
Fix style scale factor inheritance
Browse files Browse the repository at this point in the history
Commit ede4953 introduced SIZEUNITS inheritance layer->class->style/label.
When LAYER STYLEITEM is in use, for each feature msUpdateStyleFromString
is called but no attempts are made to ensure correct scale factor values
for newly created style item thus all features get scale factor 1.0,
that might be different from value it should have. This wasn't a problem
before ede4953 as layer scale factor was always used to render features
with STYLEITEM.

This commit introduces a workaround by lifting out code from the only
place where scale factor is adjusted in a way that it can be reused also
in the STYLEITEM case.
  • Loading branch information
marisn committed Jul 17, 2024
1 parent 148c68d commit 6facda6
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 66 deletions.
154 changes: 88 additions & 66 deletions src/mapdraw.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,92 @@
#include "mapows.h"
#include "cpl_port.h"

/* msGetGeoCellSize
*
* A helper function to get the first parameter for msUpdateClassScaleFactor()
*/
double msGetGeoCellSize(const mapObj *map)
{
double geo_cellsize;

/* We will need a cellsize that represents a real georeferenced */
/* coordinate cellsize here, so compute it from saved extents. */

geo_cellsize = map->cellsize;
if (map->gt.need_geotransform == MS_TRUE) {
double cellsize_x =
(map->saved_extent.maxx - map->saved_extent.minx) / map->width;
double cellsize_y =
(map->saved_extent.maxy - map->saved_extent.miny) / map->height;

geo_cellsize =
sqrt(cellsize_x * cellsize_x + cellsize_y * cellsize_y) / sqrt(2.0);
}
return geo_cellsize;
}

/* msUpdateClassScaleFactor
*
* Provides correct scale factor inheritance for Class and all of its
* styles and labels.
*/
void msUpdateClassScaleFactor(double geo_cellsize, const mapObj *map, const layerObj *layer, classObj *c)
{
if (c->sizeunits == MS_INHERIT)
c->scalefactor = layer->scalefactor;
else if (c->sizeunits != MS_PIXELS)
c->scalefactor = (msInchesPerUnit(c->sizeunits, 0) /
msInchesPerUnit(map->units, 0)) /
geo_cellsize;
else if (layer->symbolscaledenom > 0 && map->scaledenom > 0)
c->scalefactor = layer->symbolscaledenom / map->scaledenom *
map->resolution / map->defresolution;
else
c->scalefactor = map->resolution / map->defresolution;
for (int sid = 0; sid < c->numstyles; sid++) {
styleObj *style = c->styles[sid];
if (style->sizeunits == MS_INHERIT)
style->scalefactor = c->scalefactor;
else if (style->sizeunits != MS_PIXELS)
style->scalefactor = (msInchesPerUnit(style->sizeunits, 0) /
msInchesPerUnit(map->units, 0)) /
geo_cellsize;
else if (layer->symbolscaledenom > 0 && map->scaledenom > 0)
style->scalefactor = layer->symbolscaledenom / map->scaledenom *
map->resolution / map->defresolution;
else
style->scalefactor = map->resolution / map->defresolution;
}
for (int sid = 0; sid < c->numlabels; sid++) {
labelObj *label = c->labels[sid];
if (label->sizeunits == MS_INHERIT)
label->scalefactor = c->scalefactor;
else if (label->sizeunits != MS_PIXELS)
label->scalefactor = (msInchesPerUnit(label->sizeunits, 0) /
msInchesPerUnit(map->units, 0)) /
geo_cellsize;
else if (layer->symbolscaledenom > 0 && map->scaledenom > 0)
label->scalefactor = layer->symbolscaledenom / map->scaledenom *
map->resolution / map->defresolution;
else
label->scalefactor = map->resolution / map->defresolution;
for (int lsid = 0; lsid < label->numstyles; lsid++) {
styleObj *lstyle = label->styles[lsid];
if (lstyle->sizeunits == MS_INHERIT)
lstyle->scalefactor = label->scalefactor;
else if (lstyle->sizeunits != MS_PIXELS)
lstyle->scalefactor = (msInchesPerUnit(lstyle->sizeunits, 0) /
msInchesPerUnit(map->units, 0)) /
geo_cellsize;
else if (layer->symbolscaledenom > 0 && map->scaledenom > 0)
lstyle->scalefactor = layer->symbolscaledenom / map->scaledenom *
map->resolution / map->defresolution;
else
lstyle->scalefactor = map->resolution / map->defresolution;
}
}
}

/* msPrepareImage()
*
* Returns a new imageObj ready for rendering the current map.
Expand Down Expand Up @@ -154,19 +240,7 @@ imageObj *msPrepareImage(mapObj *map, int allow_nonsquare) {
if (map->gt.need_geotransform)
msMapSetFakedExtent(map);

/* We will need a cellsize that represents a real georeferenced */
/* coordinate cellsize here, so compute it from saved extents. */

geo_cellsize = map->cellsize;
if (map->gt.need_geotransform == MS_TRUE) {
double cellsize_x =
(map->saved_extent.maxx - map->saved_extent.minx) / map->width;
double cellsize_y =
(map->saved_extent.maxy - map->saved_extent.miny) / map->height;

geo_cellsize =
sqrt(cellsize_x * cellsize_x + cellsize_y * cellsize_y) / sqrt(2.0);
}
geo_cellsize = msGetGeoCellSize(map);

/* compute layer/class/style/label scale factors now */
for (int lid = 0; lid < map->numlayers; lid++) {
Expand All @@ -182,59 +256,7 @@ imageObj *msPrepareImage(mapObj *map, int allow_nonsquare) {
layer->scalefactor = map->resolution / map->defresolution;
for (int cid = 0; cid < layer->numclasses; cid++) {
classObj *class = GET_CLASS(map, lid, cid);
if (class->sizeunits == MS_INHERIT)
class->scalefactor = layer->scalefactor;
else if (class->sizeunits != MS_PIXELS)
class->scalefactor = (msInchesPerUnit(class->sizeunits, 0) /
msInchesPerUnit(map->units, 0)) /
geo_cellsize;
else if (layer->symbolscaledenom > 0 && map->scaledenom > 0)
class->scalefactor = layer->symbolscaledenom / map->scaledenom *
map->resolution / map->defresolution;
else
class->scalefactor = map->resolution / map->defresolution;
for (int sid = 0; sid < class->numstyles; sid++) {
styleObj *style = class->styles[sid];
if (style->sizeunits == MS_INHERIT)
style->scalefactor = class->scalefactor;
else if (style->sizeunits != MS_PIXELS)
style->scalefactor = (msInchesPerUnit(style->sizeunits, 0) /
msInchesPerUnit(map->units, 0)) /
geo_cellsize;
else if (layer->symbolscaledenom > 0 && map->scaledenom > 0)
style->scalefactor = layer->symbolscaledenom / map->scaledenom *
map->resolution / map->defresolution;
else
style->scalefactor = map->resolution / map->defresolution;
}
for (int sid = 0; sid < class->numlabels; sid++) {
labelObj *label = class->labels[sid];
if (label->sizeunits == MS_INHERIT)
label->scalefactor = class->scalefactor;
else if (label->sizeunits != MS_PIXELS)
label->scalefactor = (msInchesPerUnit(label->sizeunits, 0) /
msInchesPerUnit(map->units, 0)) /
geo_cellsize;
else if (layer->symbolscaledenom > 0 && map->scaledenom > 0)
label->scalefactor = layer->symbolscaledenom / map->scaledenom *
map->resolution / map->defresolution;
else
label->scalefactor = map->resolution / map->defresolution;
for (int lsid = 0; lsid < label->numstyles; lsid++) {
styleObj *lstyle = label->styles[lsid];
if (lstyle->sizeunits == MS_INHERIT)
lstyle->scalefactor = label->scalefactor;
else if (lstyle->sizeunits != MS_PIXELS)
lstyle->scalefactor = (msInchesPerUnit(lstyle->sizeunits, 0) /
msInchesPerUnit(map->units, 0)) /
geo_cellsize;
else if (layer->symbolscaledenom > 0 && map->scaledenom > 0)
lstyle->scalefactor = layer->symbolscaledenom / map->scaledenom *
map->resolution / map->defresolution;
else
lstyle->scalefactor = map->resolution / map->defresolution;
}
}
msUpdateClassScaleFactor(geo_cellsize, map, layer, class);
}
}

Expand Down
5 changes: 5 additions & 0 deletions src/maplayer.c
Original file line number Diff line number Diff line change
Expand Up @@ -1395,6 +1395,9 @@ int msLayerGetFeatureStyle(mapObj *map, layerObj *layer, classObj *c,
}

msUpdateStyleFromString(c->styles[0], stylestring);
double geo_cellsize = msGetGeoCellSize(map);
msUpdateClassScaleFactor(geo_cellsize, map, layer, c);

if (c->styles[0]->symbolname) {
if ((c->styles[0]->symbol = msGetSymbolIndex(
&(map->symbolset), c->styles[0]->symbolname, MS_TRUE)) == -1) {
Expand All @@ -1412,6 +1415,8 @@ int msLayerGetFeatureStyle(mapObj *map, layerObj *layer, classObj *c,
c->layer = layer;
}
msUpdateClassFromString(c, stylestring);
double geo_cellsize = msGetGeoCellSize(map);
msUpdateClassScaleFactor(geo_cellsize, map, layer, c);
} else if (strncasecmp(stylestring, "pen", 3) == 0 ||
strncasecmp(stylestring, "brush", 5) == 0 ||
strncasecmp(stylestring, "symbol", 6) == 0 ||
Expand Down
3 changes: 3 additions & 0 deletions src/mapserver.h
Original file line number Diff line number Diff line change
Expand Up @@ -3282,6 +3282,9 @@ rectObj msUVRASTERGetSearchRect(layerObj *layer, mapObj *map);
/* Prototypes for functions in mapdraw.c */
/* ==================================================================== */

MS_DLL_EXPORT double msGetGeoCellSize(const mapObj *map);
MS_DLL_EXPORT void msUpdateClassScaleFactor(double geo_cellsize, const mapObj *map,
const layerObj *layer, classObj *c);
MS_DLL_EXPORT imageObj *msPrepareImage(mapObj *map, int allow_nonsquare);
MS_DLL_EXPORT imageObj *msDrawMap(mapObj *map, int querymap);
MS_DLL_EXPORT int msLayerIsVisible(mapObj *map, layerObj *layer);
Expand Down

0 comments on commit 6facda6

Please sign in to comment.