qgis / QGIS

QGIS is a free, open source, cross platform (lin/win/mac) geographical information system (GIS)
https://qgis.org
GNU General Public License v2.0
10.52k stars 2.99k forks source link

Can't use vertex editing on some Features in exported GeoJSONs with mix of null and numbered ids #51415

Closed Multihuntr closed 1 year ago

Multihuntr commented 1 year ago

What is the bug or the crash?

The vertex editing tool doesn't interact at all with some points in GeoJSONs (exported with QGIS and added to the map) when there is a mix of null and numbered ids. The features with null id are then tied to features with numbered ids by the interface. For example, if you number the first two points, but give the following 4 points null ids, then you can only interact with the last 4 points, but editing some of these these can create unexpected changes in the first two points.

It seems that QGIS is confusing the n-th null id feature with the feature with id equal to that n. Hovering null id features will highlight the feature with id equal to the order in which those null features were created. It is easiest for me to explain what's happening in pseudo-code.

# Let's say you created features with ids in this order:
feature_ids = [3, 5, 2, 1, 4, null, null, null, null, null, null, null, null]
# and we have a list of `features`
# Then:
# hovering features[5] will highlight features[5]
# hovering features[6] will highlight features[3]
# hovering features[7] will highlight features[2]
# hovering features[8] will highlight features[0]
# hovering features[9] will highlight features[4]
# hovering features[10] will highlight features[1]

If you move the vertex while the wrong feature is highlighted, the numbered feature will move to the mouse location, and the feature with a null id will be removed. If you undo that operation, the null id feature you used will now be the feature that can't be interacted with. From here, moving the numbered feature will remove its respective null id feature, but when you save the layer edits, the null feature returns unchanged.

Here's a GeoJSON I created using my "Steps to reproduce". You can load this in QGIS to observe the problems.

Polygons GeoJSON ```python { "type": "FeatureCollection", "name": "polygon_", "crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } }, "features": [ { "type": "Feature", "properties": { "id": 3 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -1.226373626373626, 0.802197802197802 ], [ -1.081318681318681, 0.806593406593407 ], [ -1.085714285714286, 0.694505494505494 ], [ -1.215384615384615, 0.696703296703297 ], [ -1.226373626373626, 0.802197802197802 ] ] ] ] } }, { "type": "Feature", "properties": { "id": 5 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -0.90989010989011, 0.802197802197802 ], [ -0.775824175824176, 0.804395604395604 ], [ -0.784615384615384, 0.69010989010989 ], [ -0.907692307692308, 0.694505494505494 ], [ -0.90989010989011, 0.802197802197802 ] ] ] ] } }, { "type": "Feature", "properties": { "id": 2 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -0.586813186813187, 0.795604395604396 ], [ -0.441758241758242, 0.802197802197802 ], [ -0.446153846153846, 0.703296703296703 ], [ -0.575824175824176, 0.701098901098901 ], [ -0.586813186813187, 0.795604395604396 ] ] ] ] } }, { "type": "Feature", "properties": { "id": 1 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -0.268131868131868, 0.795604395604396 ], [ -0.096703296703297, 0.802197802197802 ], [ -0.103296703296703, 0.70989010989011 ], [ -0.265934065934066, 0.712087912087912 ], [ -0.268131868131868, 0.795604395604396 ] ] ] ] } }, { "type": "Feature", "properties": { "id": 4 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 0.072527472527473, 0.797802197802198 ], [ 0.213186813186813, 0.793406593406593 ], [ 0.204395604395605, 0.703296703296703 ], [ 0.076923076923077, 0.712087912087912 ], [ 0.072527472527473, 0.797802197802198 ] ] ] ] } }, { "type": "Feature", "properties": { "id": null }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -1.173626373626373, 0.525274725274725 ], [ -1.092307692307692, 0.417582417582418 ], [ -1.228571428571428, 0.415384615384615 ], [ -1.173626373626373, 0.525274725274725 ] ] ] ] } }, { "type": "Feature", "properties": { "id": null }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -0.916483516483516, 0.432967032967033 ], [ -0.848351648351648, 0.545054945054945 ], [ -0.802197802197802, 0.428571428571429 ], [ -0.916483516483516, 0.432967032967033 ] ] ] ] } }, { "type": "Feature", "properties": { "id": null }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -0.567032967032967, 0.446153846153846 ], [ -0.503296703296703, 0.538461538461538 ], [ -0.446153846153846, 0.428571428571429 ], [ -0.567032967032967, 0.446153846153846 ] ] ] ] } }, { "type": "Feature", "properties": { "id": null }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -0.248351648351648, 0.446153846153846 ], [ -0.191208791208791, 0.545054945054945 ], [ -0.138461538461538, 0.443956043956044 ], [ -0.248351648351648, 0.446153846153846 ] ] ] ] } }, { "type": "Feature", "properties": { "id": null }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 0.063736263736264, 0.459340659340659 ], [ 0.156043956043956, 0.558241758241758 ], [ 0.226373626373626, 0.450549450549451 ], [ 0.063736263736264, 0.459340659340659 ] ] ] ] } }, { "type": "Feature", "properties": { "id": null }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 0.386813186813187, 0.446153846153846 ], [ 0.483516483516484, 0.553846153846154 ], [ 0.547252747252747, 0.446153846153846 ], [ 0.386813186813187, 0.446153846153846 ] ] ] ] } }, { "type": "Feature", "properties": { "id": null }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 0.679120879120879, 0.43956043956044 ], [ 0.782417582417583, 0.556043956043956 ], [ 0.85934065934066, 0.43956043956044 ], [ 0.679120879120879, 0.43956043956044 ] ] ] ] } } ] } ```
Save Feature As... 8. Select GeoJSON, use all default settings. 9. Select newly added GeoJSON layer. 10. Toggle editing 11. Select "Vertex Tool" 12. Hover mouse near the first two numbered geometries. 13. Observe that the vertex tool doesn't recognise the geometries properly The same thing happens if you export as GeoJSON after creating just one of the features, and then adding the rest. But only after saving layer edits. ### Versions QGIS version | 3.26.3-Buenos Aires | QGIS code revision | 65e4edfdad -- | -- | -- | -- Qt version | 5.12.8 Python version | 3.8.10 GDAL/OGR version | 3.0.4 PROJ version | 6.3.1 EPSG Registry database version | v9.8.6 (2020-01-22) Compiled against GEOS | 3.8.0-CAPI-1.13.1 | Running against GEOS | 3.8.0-CAPI-1.13.1 SQLite version | 3.31.1 PDAL version | 2.0.1 PostgreSQL client version | 12.12 (Ubuntu 12.12-0ubuntu0.20.04.1) SpatiaLite version | 4.3.0a QWT version | 6.1.4 QScintilla2 version | 2.11.2 OS version | Ubuntu 20.04.5 LTS   |   |   |   Active Python plugins MetaSearch | 0.3.6 sagaprovider | 2.12.99 db_manager | 0.1.20 grassprovider | 2.12.99 processing | 2.12.99 QGIS version 3.26.3-Buenos Aires QGIS code revision [65e4edfdad](https://github.com/qgis/QGIS/commit/65e4edfdad) Qt version 5.12.8 Python version 3.8.10 GDAL/OGR version 3.0.4 PROJ version 6.3.1 EPSG Registry database version v9.8.6 (2020-01-22) Compiled against GEOS 3.8.0-CAPI-1.13.1 Running against GEOS 3.8.0-CAPI-1.13.1 SQLite version 3.31.1 PDAL version 2.0.1 PostgreSQL client version 12.12 (Ubuntu 12.12-0ubuntu0.20.04.1) SpatiaLite version 4.3.0a QWT version 6.1.4 QScintilla2 version 2.11.2 OS version Ubuntu 20.04.5 LTS Active Python plugins MetaSearch 0.3.6 sagaprovider 2.12.99 db_manager 0.1.20 grassprovider 2.12.99 processing 2.12.99 ### Supported QGIS version - [X] I'm running a supported QGIS version according to the roadmap. ### New profile - [x] I tried with a new QGIS profile ### Additional context _No response_
roya0045 commented 1 year ago

I don't think it's just the vertex editor, removing some null features or even adding an ID value seems problematic. The best solution was to edit the file manually to fix the ids or remove the feature entirely.

troopa81 commented 1 year ago

This comes from OGR provider, the given GeoJSON results in some feature having the same ids. And QGIS doesn't like that.

And I think that's normal, because OGR would have to read the entire file to avoid id collision in that case, which would problematic.

It's a won't fix to me

Do you confirm @rouault ?

rouault commented 1 year ago

Not sure which GDAL version you use but with GDAL master / 3.6, here's what ogrinfo reports:

OGRFeature(polygon_):1
  id (Integer) = 1
  MULTIPOLYGON (((-0.268131868131868 0.795604395604396,-0.096703296703297 0.802197802197802,-0.103296703296703 0.70989010989011,-0.265934065934066 0.712087912087912,-0.268131868131868 0.795604395604396)))

OGRFeature(polygon_):2
  id (Integer) = 2
  MULTIPOLYGON (((-0.586813186813187 0.795604395604396,-0.441758241758242 0.802197802197802,-0.446153846153846 0.703296703296703,-0.575824175824176 0.701098901098901,-0.586813186813187 0.795604395604396)))

OGRFeature(polygon_):3
  id (Integer) = 3
  MULTIPOLYGON (((-1.22637362637363 0.802197802197802,-1.08131868131868 0.806593406593407,-1.08571428571429 0.694505494505494,-1.21538461538462 0.696703296703297,-1.22637362637363 0.802197802197802)))

OGRFeature(polygon_):4
  id (Integer) = 4
  MULTIPOLYGON (((0.072527472527473 0.797802197802198,0.213186813186813 0.793406593406593,0.204395604395605 0.703296703296703,0.076923076923077 0.712087912087912,0.072527472527473 0.797802197802198)))

OGRFeature(polygon_):5
  id (Integer) = 5
  MULTIPOLYGON (((-0.90989010989011 0.802197802197802,-0.775824175824176 0.804395604395604,-0.784615384615384 0.69010989010989,-0.907692307692308 0.694505494505494,-0.90989010989011 0.802197802197802)))

OGRFeature(polygon_):6
  id (Integer) = (null)
  MULTIPOLYGON (((-1.17362637362637 0.525274725274725,-1.09230769230769 0.417582417582418,-1.22857142857143 0.415384615384615,-1.17362637362637 0.525274725274725)))

OGRFeature(polygon_):7
  id (Integer) = (null)
  MULTIPOLYGON (((-0.916483516483516 0.432967032967033,-0.848351648351648 0.545054945054945,-0.802197802197802 0.428571428571429,-0.916483516483516 0.432967032967033)))

OGRFeature(polygon_):8
  id (Integer) = (null)
  MULTIPOLYGON (((-0.567032967032967 0.446153846153846,-0.503296703296703 0.538461538461538,-0.446153846153846 0.428571428571429,-0.567032967032967 0.446153846153846)))

OGRFeature(polygon_):9
  id (Integer) = (null)
  MULTIPOLYGON (((-0.248351648351648 0.446153846153846,-0.191208791208791 0.545054945054945,-0.138461538461538 0.443956043956044,-0.248351648351648 0.446153846153846)))

OGRFeature(polygon_):10
  id (Integer) = (null)
  MULTIPOLYGON (((0.063736263736264 0.459340659340659,0.156043956043956 0.558241758241758,0.226373626373626 0.450549450549451,0.063736263736264 0.459340659340659)))

OGRFeature(polygon_):11
  id (Integer) = (null)
  MULTIPOLYGON (((0.386813186813187 0.446153846153846,0.483516483516484 0.553846153846154,0.547252747252747 0.446153846153846,0.386813186813187 0.446153846153846)))

OGRFeature(polygon_):12
  id (Integer) = (null)
  MULTIPOLYGON (((0.679120879120879 0.43956043956044,0.782417582417583 0.556043956043956,0.85934065934066 0.43956043956044,0.679120879120879 0.43956043956044)))

so no duplication

nicogodet commented 1 year ago

GDAL/OGR version 3.0.4

A bit outdated

@Multihuntr Could you try to update gdal and QGIS ?

troopa81 commented 1 year ago

@rouault I tested it with Gdal 3.6.2 and got a different result

$ ogrinfo --version
GDAL 3.6.2, released 2023/01/02
$ ogrinfo -al ~/work/tmp/nodis.geojson
INFO: Open of `/home/julien/work/tmp/nodis.geojson'
      using driver `GeoJSON' successful.

Layer name: polygon_
Geometry: Multi Polygon
Feature Count: 12
Extent: (-1.228571, 0.415385) - (0.859341, 0.806593)
Layer SRS WKT:
GEOGCRS["WGS 84",
    DATUM["World Geodetic System 1984",
        ELLIPSOID["WGS 84",6378137,298.257223563,
            LENGTHUNIT["metre",1]]],
    PRIMEM["Greenwich",0,
        ANGLEUNIT["degree",0.0174532925199433]],
    CS[ellipsoidal,2],
        AXIS["geodetic latitude (Lat)",north,
            ORDER[1],
            ANGLEUNIT["degree",0.0174532925199433]],
        AXIS["geodetic longitude (Lon)",east,
            ORDER[2],
            ANGLEUNIT["degree",0.0174532925199433]],
    ID["EPSG",4326]]
Data axis to CRS axis mapping: 2,1
FID Column = id
id: Integer (0.0)
OGRFeature(polygon_):3
  id (Integer) = 3
  MULTIPOLYGON (((-1.22637362637363 0.802197802197802,-1.08131868131868 0.806593406593407,-1.08571428571429 0.694505494505494,-1.21538461538462 0.696703296703297,-1.22637362637363 0.802197802197802)))

OGRFeature(polygon_):5
  id (Integer) = 5
  MULTIPOLYGON (((-0.90989010989011 0.802197802197802,-0.775824175824176 0.804395604395604,-0.784615384615384 0.69010989010989,-0.907692307692308 0.694505494505494,-0.90989010989011 0.802197802197802)))

OGRFeature(polygon_):2
  id (Integer) = 2
  MULTIPOLYGON (((-0.586813186813187 0.795604395604396,-0.441758241758242 0.802197802197802,-0.446153846153846 0.703296703296703,-0.575824175824176 0.701098901098901,-0.586813186813187 0.795604395604396)))

OGRFeature(polygon_):1
  id (Integer) = 1
  MULTIPOLYGON (((-0.268131868131868 0.795604395604396,-0.096703296703297 0.802197802197802,-0.103296703296703 0.70989010989011,-0.265934065934066 0.712087912087912,-0.268131868131868 0.795604395604396)))

OGRFeature(polygon_):4
  id (Integer) = 4
  MULTIPOLYGON (((0.072527472527473 0.797802197802198,0.213186813186813 0.793406593406593,0.204395604395605 0.703296703296703,0.076923076923077 0.712087912087912,0.072527472527473 0.797802197802198)))

OGRFeature(polygon_):0
  id (Integer) = (null)
  MULTIPOLYGON (((-1.17362637362637 0.525274725274725,-1.09230769230769 0.417582417582418,-1.22857142857143 0.415384615384615,-1.17362637362637 0.525274725274725)))

OGRFeature(polygon_):1
  id (Integer) = (null)
  MULTIPOLYGON (((-0.916483516483516 0.432967032967033,-0.848351648351648 0.545054945054945,-0.802197802197802 0.428571428571429,-0.916483516483516 0.432967032967033)))

OGRFeature(polygon_):2
  id (Integer) = (null)
  MULTIPOLYGON (((-0.567032967032967 0.446153846153846,-0.503296703296703 0.538461538461538,-0.446153846153846 0.428571428571429,-0.567032967032967 0.446153846153846)))

OGRFeature(polygon_):3
  id (Integer) = (null)
  MULTIPOLYGON (((-0.248351648351648 0.446153846153846,-0.191208791208791 0.545054945054945,-0.138461538461538 0.443956043956044,-0.248351648351648 0.446153846153846)))

OGRFeature(polygon_):4
  id (Integer) = (null)
  MULTIPOLYGON (((0.063736263736264 0.459340659340659,0.156043956043956 0.558241758241758,0.226373626373626 0.450549450549451,0.063736263736264 0.459340659340659)))

OGRFeature(polygon_):5
  id (Integer) = (null)
  MULTIPOLYGON (((0.386813186813187 0.446153846153846,0.483516483516484 0.553846153846154,0.547252747252747 0.446153846153846,0.386813186813187 0.446153846153846)))

OGRFeature(polygon_):6
  id (Integer) = (null)
  MULTIPOLYGON (((0.679120879120879 0.43956043956044,0.782417582417583 0.556043956043956,0.85934065934066 0.43956043956044,0.679120879120879 0.43956043956044)))
Multihuntr commented 1 year ago

I just tested it using docker run --rm -it --name qgis -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=unix$DISPLAY qgis/qgis:release-3_28 and it has the same issue. (Using apt and the PPA was refusing to install the latest version on my Ubuntu 20.04 machine)

Version info QGIS version | 3.28.3-Firenze | QGIS code branch | Release 3.28 -- | -- | -- | -- Qt version | 5.15.3 Python version | 3.10.6 GDAL/OGR version | 3.4.1 PROJ version | 8.2.1 EPSG Registry database version | v10.041 (2021-12-03) GEOS version | 3.10.2-CAPI-1.16.0 SQLite version | 3.37.2 PostgreSQL client version | unknown SpatiaLite version | 5.0.1 QWT version | 6.1.4 QScintilla2 version | 2.11.6 OS version | Ubuntu 22.04.1 LTS   |   |   |   Active Python plugins MetaSearch | 0.3.6 sagaprovider | 2.12.99 db_manager | 0.1.20 grassprovider | 2.12.99 processing | 2.12.99 QGIS version 3.28.3-Firenze QGIS code branch [Release 3.28](https://github.com/qgis/QGIS/tree/release-3_28) Qt version 5.15.3 Python version 3.10.6 GDAL/OGR version 3.4.1 PROJ version 8.2.1 EPSG Registry database version v10.041 (2021-12-03) GEOS version 3.10.2-CAPI-1.16.0 SQLite version 3.37.2 PostgreSQL client version unknown SpatiaLite version 5.0.1 QWT version 6.1.4 QScintilla2 version 2.11.6 OS version Ubuntu 22.04.1 LTS Active Python plugins MetaSearch 0.3.6 sagaprovider 2.12.99 db_manager 0.1.20 grassprovider 2.12.99 processing 2.12.99
troopa81 commented 1 year ago

@rouault I tested also it with Gdal master and got the same wrong result

➜ build git:(master) ✗ LD_LIBRARY_PATH=$PWD/../install/lib ../install/bin/ogrinfo --version
GDAL 3.7.0dev-9ec53d9ab0, released 2023/02/15
➜  build git:(master) ✗ LD_LIBRARY_PATH=$PWD/../install/lib ../install/bin/ogrinfo  -al ~/work/tmp/nodis.geojson
INFO: Open of `/home/julien/work/tmp/nodis.geojson'
      using driver `GeoJSON' successful.

Layer name: polygon_
Geometry: Multi Polygon
Feature Count: 12
Extent: (-1.228571, 0.415385) - (0.859341, 0.806593)
Layer SRS WKT:
GEOGCRS["WGS 84",
    DATUM["World Geodetic System 1984",
        ELLIPSOID["WGS 84",6378137,298.257223563,
            LENGTHUNIT["metre",1]]],
    PRIMEM["Greenwich",0,
        ANGLEUNIT["degree",0.0174532925199433]],
    CS[ellipsoidal,2],
        AXIS["geodetic latitude (Lat)",north,
            ORDER[1],
            ANGLEUNIT["degree",0.0174532925199433]],
        AXIS["geodetic longitude (Lon)",east,
            ORDER[2],
            ANGLEUNIT["degree",0.0174532925199433]],
    ID["EPSG",4326]]
Data axis to CRS axis mapping: 2,1
FID Column = id
id: Integer (0.0)
OGRFeature(polygon_):3
  id (Integer) = 3
  MULTIPOLYGON (((-1.22637362637363 0.802197802197802,-1.08131868131868 0.806593406593407,-1.08571428571429 0.694505494505494,-1.21538461538462 0.696703296703297,-1.22637362637363 0.802197802197802)))

OGRFeature(polygon_):5
  id (Integer) = 5
  MULTIPOLYGON (((-0.90989010989011 0.802197802197802,-0.775824175824176 0.804395604395604,-0.784615384615384 0.69010989010989,-0.907692307692308 0.694505494505494,-0.90989010989011 0.802197802197802)))

OGRFeature(polygon_):2
  id (Integer) = 2
  MULTIPOLYGON (((-0.586813186813187 0.795604395604396,-0.441758241758242 0.802197802197802,-0.446153846153846 0.703296703296703,-0.575824175824176 0.701098901098901,-0.586813186813187 0.795604395604396)))

OGRFeature(polygon_):1
  id (Integer) = 1
  MULTIPOLYGON (((-0.268131868131868 0.795604395604396,-0.096703296703297 0.802197802197802,-0.103296703296703 0.70989010989011,-0.265934065934066 0.712087912087912,-0.268131868131868 0.795604395604396)))

OGRFeature(polygon_):4
  id (Integer) = 4
  MULTIPOLYGON (((0.072527472527473 0.797802197802198,0.213186813186813 0.793406593406593,0.204395604395605 0.703296703296703,0.076923076923077 0.712087912087912,0.072527472527473 0.797802197802198)))

OGRFeature(polygon_):0
  id (Integer) = (null)
  MULTIPOLYGON (((-1.17362637362637 0.525274725274725,-1.09230769230769 0.417582417582418,-1.22857142857143 0.415384615384615,-1.17362637362637 0.525274725274725)))

OGRFeature(polygon_):1
  id (Integer) = (null)
  MULTIPOLYGON (((-0.916483516483516 0.432967032967033,-0.848351648351648 0.545054945054945,-0.802197802197802 0.428571428571429,-0.916483516483516 0.432967032967033)))

OGRFeature(polygon_):2
  id (Integer) = (null)
  MULTIPOLYGON (((-0.567032967032967 0.446153846153846,-0.503296703296703 0.538461538461538,-0.446153846153846 0.428571428571429,-0.567032967032967 0.446153846153846)))

OGRFeature(polygon_):3
  id (Integer) = (null)
  MULTIPOLYGON (((-0.248351648351648 0.446153846153846,-0.191208791208791 0.545054945054945,-0.138461538461538 0.443956043956044,-0.248351648351648 0.446153846153846)))

OGRFeature(polygon_):4
  id (Integer) = (null)
  MULTIPOLYGON (((0.063736263736264 0.459340659340659,0.156043956043956 0.558241758241758,0.226373626373626 0.450549450549451,0.063736263736264 0.459340659340659)))

OGRFeature(polygon_):5
  id (Integer) = (null)
  MULTIPOLYGON (((0.386813186813187 0.446153846153846,0.483516483516484 0.553846153846154,0.547252747252747 0.446153846153846,0.386813186813187 0.446153846153846)))

OGRFeature(polygon_):6
  id (Integer) = (null)
  MULTIPOLYGON (((0.679120879120879 0.43956043956044,0.782417582417583 0.556043956043956,0.85934065934066 0.43956043956044,0.679120879120879 0.43956043956044)))
rouault commented 1 year ago

I tested also it with Gdal master and got the same wrong result

oh interesting, I also do get the wrong result... when I do "ogrinfo the.geojson". But what I tried was the not so know possibility of passing the GeoJSON content as the dataset connection string, so "ogrinfo '{ "type": "FeatureCollection", .... }'", and that returns sequential FIDs.

troopa81 commented 1 year ago

I opened a Gdal issue https://github.com/OSGeo/gdal/issues/7258

I close this one as upstream