Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WMS legend symbol missing for "Meters at Scale" symbology and projected CRS #50366

Closed
1 of 2 tasks
itsakifa opened this issue Sep 27, 2022 · 5 comments · Fixed by #52015
Closed
1 of 2 tasks

WMS legend symbol missing for "Meters at Scale" symbology and projected CRS #50366

itsakifa opened this issue Sep 27, 2022 · 5 comments · Fixed by #52015
Labels
Bug Either a bug report, or a bug fix. Let's hope for the latter! Map and Legend Related to map or legend rendering Server Related to QGIS server WMS data provider

Comments

@itsakifa
Copy link

What is the bug or the crash?

The legend symbol of a vector layer having a meters at scale symbology and rendered as WMS via QGIS Server is missing if using a projected CRS.

A workaround has been found when setting Project Properties > QGIS Server > WMS Capabilities > Default scale for legend as > 1, like 10:1. In that case, the legend symbol of the WMS layer is shown.

Is this supposed to be normal behaviour? Standard scales that can be chosen from the dropdown do not include scales >1:1, so I guess it's not normal.

For WGS84, it's "Default map units per mm in legend" that can be defined. Is it possible that even when it's saying "Default scale for legend" for other CRS, the value entered is still translated as map units per mm?

Screenshot 2022-09-27 at 10 59 12

Steps to reproduce the issue

  1. Open a new QGIS project with CRS = EPSG:2056
  2. Add a vector layer (e.g. lines)
  3. Draw a feature
  4. Define Symbology > Stroke width = 5, Meters at Scale
  5. Go to Project properties > QGIS Server > WMS capabilities, set Default scale for legend to 1:1000 or something else 1:>1
  6. Run a local QGIS server (e.g. with docker)
  7. Open another QGIS project and add WMS layer from your project on the local server, add the line layer
  8. See that there is no legend symbol

Redo the same from point 5 on, setting the Default scale for legend to something >1:1

Versions

<style type="text/css"> p, li { white-space: pre-wrap; } </style>
QGIS version 3.22.4-Białowieża QGIS code revision 3f4577c
Qt version 5.14.2
Python version 3.8.7
GDAL/OGR version 3.2.1
PROJ version 6.3.2
EPSG Registry database version v9.8.6 (2020-01-22)
GEOS version 3.9.1-CAPI-1.14.2
SQLite version 3.31.1
PostgreSQL client version 12.3
SpatiaLite version 4.3.0a
QWT version 6.1.4
QScintilla2 version 2.11.4
OS version macOS 12.6
       
Active Python plugins
numericalDigitize 0.4.7
firstaid 2.1.5
lrs 1.2.2
precipitation_plugin dev
DataPlotly master
quick_map_services 0.19.29
vertex_compare 0.0.1
linking_relation_editor v1.0.0
QgisModelBaker v7.1.7
HCMGIS 22.9.9
qfieldsync v4.1.1
swissgeodownloader 2.0
document_management_system 0.3.1
PointConnector 2.0
qgis_resource_sharing 0.16.0
plugin_reloader 0.9.1
swiss_locator 2.0.0
coordinate_capture 0.2
processing 2.12.99
sagaprovider 2.12.99
grassprovider 2.12.99
db_manager 0.1.20
MetaSearch 0.3.5
QGIS version 3.22.4-Białowieża QGIS code revision [3f4577c](https://github.com/qgis/QGIS/commit/3f4577ce6e) Qt version 5.14.2 Python version 3.8.7 GDAL/OGR version 3.2.1 PROJ version 6.3.2 EPSG Registry database version v9.8.6 (2020-01-22) GEOS version 3.9.1-CAPI-1.14.2 SQLite version 3.31.1 PostgreSQL client version 12.3 SpatiaLite version 4.3.0a QWT version 6.1.4 QScintilla2 version 2.11.4 OS version macOS 12.6

Supported QGIS version

  • I'm running a supported QGIS version according to the roadmap.

New profile

  • I tried with a new QGIS profile

Additional context

No response

@itsakifa itsakifa added the Bug Either a bug report, or a bug fix. Let's hope for the latter! label Sep 27, 2022
@itsakifa
Copy link
Author

@domi4484 : could you have a look on that?

@agiudiceandrea
Copy link
Contributor

Maybe related to #49858 - #49930?

@agiudiceandrea agiudiceandrea added Map and Legend Related to map or legend rendering Server Related to QGIS server WMS data provider labels Sep 27, 2022
@pathmapper
Copy link
Contributor

pathmapper commented Sep 27, 2022

Hi, maybe duplicate of #49859 ?

Edit: #49859 is for Desktop, this issue here is for Server (could be the same underlying issue).

@signedav
Copy link
Contributor

signedav commented Nov 23, 2022

I checked out the code a little, but did not finished. Meanwhile I note down conclusions:

  1. Default Scale for Legend is converted to mU/mm on saving the settings:

    double defaultMapUnitsPerMm = mWMSDefaultMapUnitScale->scale() / QgsUnitTypes::fromUnitToUnitFactor( QgsProject::instance()->crs().mapUnits(), QgsUnitTypes::DistanceMillimeters );
    

    This is stored then to the setting: "WMSDefaultMapUnitsPerMm"
    Means on 1:1000 we have 1 mU/mm

  2. Only when no BBOX is passed in the command, this value is considered in QgsLegendSettings QgsRenderer::legendSettings():
    Without BBOX:

    defaultMapUnitsPerPixel = QgsServerProjectUtils::wmsDefaultMapUnitsPerMm( *mContext.project() ) / mContext.dotsPerMm();
    

    while this division appears weird. Shouldn't it be a multiplication?

    With this we have 1 mU/mm divided with e.g. 3.57 leading to 0.28 mU/pixel.

    With BBOX:
    mapSettings.mapUnitsPerPixel() what is in our case 28.273 mU/pixel (on a bbox scale 100975)

    Both cases:
    After that it's set here QgsLegendSettings::setMapUnitsPerPixel where other fancy calculations are done:

    mMmPerMapUnit = 1 / mapUnitsPerPixel / ( mDpi / 25.4 );
    

    Where mDpi is 96 (per default).

    Leads to mm/mU 0.944940476 (on 0.28 mU/pixel) and to mm/mU 0.116402698 (on 28.273 mU/pixel).

  3. On making a multiplication instead of division in the step where we get the defaultMapUnitsPerPixel I would have a result (without BBOX) and on making the default scale 1:10 I would have a result (without BBOX) even without multiplication instead of division.

Now my head explodes a little bit, and I have to stop working. Next step would be:

  • validate if it works with EPSG 4326 where we set the mapUnits per MM (what @domi4484 told it's working, but in my case it's not, but I did not make proper checks).
  • check what is done after setting the mMmPerMapUnit? How is it used and where and are there made additional modifications?

Maybe the division-instead-multiplication thingy is a bug that needs to be fixed and everything works well, but not sure ATM.

Note: Fprget about this division-instead-multiplication thingy - It's not the case.

Note: Apparently in QGIS code dots are equal pixels...

Another Note It's working with EPSG:4326

@signedav
Copy link
Contributor

signedav commented Feb 1, 2023

Short

The issue is that we do not set the CRS on the distanceArea of the QgsRenderContext and with that the default one is used (EPSG:4326) using Degrees instead of Meters as MapUnits, what gives us suuupersmall symbols on Meter-based CRS...

This can be solved by setting the corrects CRS, like e.g.

    const QgsCoordinateTransformContext cordcontext;
    distanceArea.setSourceCrs( QgsCoordinateReferenceSystem( mWmsParameters.crs() ), cordcontext );
    distanceArea.setEllipsoid( geoNone() );
    context.setDistanceArea(distanceArea);

But not sure if we can do that...

TL:DR - Backgroundinfo

  1. Default Scale for Legend is converted to mU/mm on saving the settings:

    double defaultMapUnitsPerMm = mWMSDefaultMapUnitScale->scale() / QgsUnitTypes::fromUnitToUnitFactor( QgsProject::instance()->crs().mapUnits(), QgsUnitTypes::DistanceMillimeters );
    

    This is stored then to the setting: "WMSDefaultMapUnitsPerMm"

    Means on 1:39542 we have 39.542 mU/mm

  2. Now we need to set it in QgsLegendSettings QgsRenderer::legendSettings():

    Without BBOX:

    The wmsDefaultMapUnitsPerMm is used.

    defaultMapUnitsPerPixel = QgsServerProjectUtils::wmsDefaultMapUnitsPerMm( *mContext.project() ) / mContext.dotsPerMm();
    

    With this we have 39.542 mU/mm divided with e.g. 3.57 leading to 11.0718 mU/pixel.

    With BBOX:

    (we tried to make a more or less same bbox with the same scale)

    mapSettings.mapUnitsPerPixel() what is in our case 11.3052 mU/pixel

    Both cases:
    After that it's set here QgsLegendSettings::setMapUnitsPerPixel where other fancy calculations are done:

    mMmPerMapUnit = 1 / mapUnitsPerPixel / ( mDpi / 25.4 );
    

    Where mDpi is 96 (per default).

    Leads to mm/mU 0.023897048 (on 11.0718 mU/pixel) and to mm/mU 0.023403684 (on 11.3052 mU/pixel).

    And in QgsLegendSettings::mapUnitsPerPixel() it's calculated back to mU/px, but this is never done. Instead we do in QgsRenderer::getLegendGraphics:

    //setting the scale factor
    context.setRendererScale( settings.mapScale() );
    //calculating map units per pixel (again)
    context.setMapToPixel( QgsMapToPixel( 1 / ( settings.mmPerMapUnit() * context.scaleFactor() ) ) );
    

    With BBOX:

    And since we have a scale of 40375.7 this leads to a scale factor of 3.58268 this leads to:

    QgsMapToPixel( 1 / ( settings.mmPerMapUnit() * context.scaleFactor() ) ) => QgsMapToPixel( 1 / ( 0.023403684 * 3.58268 ) )
    `

    (While in QgsMapToPixel should be passed mU/px)

    And with this we are back again on our 11.3052 mU/pixel.

    We end up here QgsSymbolLegendNode::drawSymbol where we do this:

    const double size = markerSymbol->size( *context ) / context->scaleFactor();
    

    And have this size (with and height) now: 2.10239e-05 (0.0000210239)

    Then we read dotsPerMM = context->scaleFactor(); again what is 3.58268.

    And in the end we calculate the with and the hight like this: std::round( width * dotsPerMM ) )

    Means we are on 0 now...

    And no legend symbol with both:

    image

  3. Where do we go on...

    It seems that this value here is way to small:

    And have this size (with and height) now: 2.10239e-05 (0.0000210239)

    We get it here here QgsSymbolLegendNode::drawSymbol where we do this:

    const double size = markerSymbol->size( *context ) / context->scaleFactor();
    

    In the size() we call QgsRenderContext::convertToPainterUnits and there we do this:

    size = convertMetersToMapUnits( size );
    

    Now this should not change the size. Because our map unit is meters. I thought. But apparantely not. We end up here QgsRenderContext::convertMetersToMapUnits with QgsUnitTypes::DistanceDegrees as mDistanceArea.sourceCrs().mapUnits() because the default SRS is EPSG:4326 set in the construtor of QgsDistanceArea.

    What we need to do now? Set somewhere the correct CRS in the QgsDistanceArea. Maybe in getLegendGraphics...

signedav added a commit to signedav/QGIS that referenced this issue Feb 6, 2023
signedav added a commit to signedav/QGIS that referenced this issue Feb 8, 2023
… available to handle properly symbols that are defined as meters at scale. This fixes qgis#50366
signedav added a commit to signedav/QGIS that referenced this issue Feb 13, 2023
… available to handle properly symbols that are defined as meters at scale. This fixes qgis#50366
signedav added a commit to signedav/QGIS that referenced this issue Feb 24, 2023
…correct CRS and care about meter based crs. This fixes qgis#50366
qgis-bot pushed a commit that referenced this issue Mar 7, 2023
…correct CRS and care about meter based crs. This fixes #50366
signedav added a commit that referenced this issue Mar 8, 2023
…correct CRS and care about meter based crs. This fixes #50366
m-kuhn pushed a commit to m-kuhn/QGIS that referenced this issue Mar 31, 2023
…correct CRS and care about meter based crs. This fixes qgis#50366
nyalldawson pushed a commit that referenced this issue Apr 1, 2023
…correct CRS and care about meter based crs. This fixes #50366
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Either a bug report, or a bug fix. Let's hope for the latter! Map and Legend Related to map or legend rendering Server Related to QGIS server WMS data provider
Projects
None yet
4 participants