From 3a23f5fd1fd23fa7cbeda11f642619c8db412c70 Mon Sep 17 00:00:00 2001 From: uclaros Date: Tue, 16 Jun 2026 20:07:34 +0300 Subject: [PATCH 1/4] Recalculate Vertex markers whenever the scale changes --- app/map/inputmapsettings.cpp | 5 +++++ app/map/inputmapsettings.h | 3 +++ app/maptools/recordingmaptool.h | 10 ++++++---- app/qml/map/MMMapController.qml | 10 ++++++++++ 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/app/map/inputmapsettings.cpp b/app/map/inputmapsettings.cpp index a529313e3..2dfcfe09a 100644 --- a/app/map/inputmapsettings.cpp +++ b/app/map/inputmapsettings.cpp @@ -81,8 +81,13 @@ void InputMapSettings::setExtent( const QgsRectangle &extent ) if ( mMapSettings.extent() == extent ) return; + const bool scaleDidChange = !qgsDoubleNear( mMapSettings.extent().width(), extent.width() ); + mMapSettings.setExtent( extent ); emit extentChanged(); + + if ( scaleDidChange ) + emit scaleChanged(); } QgsPoint InputMapSettings::center() const diff --git a/app/map/inputmapsettings.h b/app/map/inputmapsettings.h index e8fac298e..a27e1883a 100644 --- a/app/map/inputmapsettings.h +++ b/app/map/inputmapsettings.h @@ -290,6 +290,9 @@ class InputMapSettings : public QObject //! \copydoc InputMapSettings::extent void extentChanged(); + //! Fired after extentChanged() if the new extent is on a different map scale + void scaleChanged(); + //! \copydoc InputMapSettings::destinationCrs void destinationCrsChanged(); diff --git a/app/maptools/recordingmaptool.h b/app/maptools/recordingmaptool.h index 0587fde9c..efc5d49ce 100644 --- a/app/maptools/recordingmaptool.h +++ b/app/maptools/recordingmaptool.h @@ -278,17 +278,19 @@ class RecordingMapTool : public AbstractMapTool public slots: void onPositionChanged(); - private slots: - void prepareEditing(); - void onFeatureAdded( QgsFeatureId newFeatureId ); - /** * Creates nodes index. Extracts existing geometry vertices and generates virtual * vertices representing midpoints (for lines and polygons) and start/end points * (for lines). + * This is also called whenever the map scale changes so that start/end point positions + * can have a stable pixel offset. Also to skip midpoints for segments below a size threshold. */ void collectVertices(); + private slots: + void prepareEditing(); + void onFeatureAdded( QgsFeatureId newFeatureId ); + /** * Creates geometries represeinting existing nodes, midpoints (for lines and polygons), * start/end points and "handles" (for lines) from the nodes index. diff --git a/app/qml/map/MMMapController.qml b/app/qml/map/MMMapController.qml index 158700fd8..0ffce7e85 100644 --- a/app/qml/map/MMMapController.qml +++ b/app/qml/map/MMMapController.qml @@ -1239,6 +1239,16 @@ Item { } } + + Connections { + target: mapCanvas.mapSettings + function onScaleChanged() { + if ( recordingToolsLoader.active ) { + recordingToolsLoader.item.recordingMapTool.collectVertices() + } + } + } + Connections { target: __activeProject From 60bdf3cbcfe53e43e99d723908825a72f0a318d8 Mon Sep 17 00:00:00 2001 From: uclaros Date: Tue, 16 Jun 2026 20:08:15 +0300 Subject: [PATCH 2/4] Increase the line Start and End marker distance in pixels --- app/maptools/recordingmaptool.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/maptools/recordingmaptool.cpp b/app/maptools/recordingmaptool.cpp index 6a8341ce2..740897cfe 100644 --- a/app/maptools/recordingmaptool.cpp +++ b/app/maptools/recordingmaptool.cpp @@ -1314,7 +1314,8 @@ QgsPoint RecordingMapTool::handlePoint( QgsPoint p1, QgsPoint p2 ) return QgsPoint(); } - double h = 15 * mapSettings()->mapUnitsPerPixel(); + constexpr int HANDLE_PIXEL_OFFSET = 42; + double h = HANDLE_PIXEL_OFFSET * mapSettings()->mapUnitsPerPixel(); double factor = QgsUnitTypes::fromUnitToUnitFactor( mapSettings()->destinationCrs().mapUnits(), mActiveLayer->crs().mapUnits() ); QgsDistanceArea da; da.setEllipsoid( QStringLiteral( "WGS84" ) ); From 9b212fc79ad850dc59691913d3ce4ee1fa180342 Mon Sep 17 00:00:00 2001 From: uclaros Date: Tue, 16 Jun 2026 20:12:42 +0300 Subject: [PATCH 3/4] Use the QT 6.6+ CurveRenderer for rendering dashed highlights. If geometry is off-screen upon creation, dashed highlights are generated as empty/zero-length. The new CurveRenderer uses the GPU and does not suffer from this bug. --- app/qml/map/MMHighlight.qml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/qml/map/MMHighlight.qml b/app/qml/map/MMHighlight.qml index fb16f35a4..d52f8bd46 100644 --- a/app/qml/map/MMHighlight.qml +++ b/app/qml/map/MMHighlight.qml @@ -280,6 +280,10 @@ Item { id: shape anchors.fill: parent + // The newer CurveRenderer is used for dashed lines to avoid a bug causing off-screen lines to be generated as empty + // see https://github.com/MerginMaps/mobile/issues/2280 + preferredRendererType: highlight.lineStrokeStyle === ShapePath.DashLine ? Shape.CurveRenderer : Shape.UnknownRenderer + transform: Matrix4x4 { // the formula for x coordinate for map to screen coordinates conversion goes like this: // x_screen = (x_map + offset_x) * scale / ddp From 05027e32a9b5215a58cd9b76798233b98c69954c Mon Sep 17 00:00:00 2001 From: uclaros Date: Tue, 21 Jul 2026 16:37:21 +0300 Subject: [PATCH 4/4] Adjust tests for start-end handles' new coords --- app/test/testmaptools.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/test/testmaptools.cpp b/app/test/testmaptools.cpp index 2b7176a5c..fc70b296d 100644 --- a/app/test/testmaptools.cpp +++ b/app/test/testmaptools.cpp @@ -571,10 +571,10 @@ void TestMapTools::testMidSegmentVertices() vertices = mapTool.midPoints(); QCOMPARE( vertices.wkbType(), Qgis::WkbType::MultiPoint ); QCOMPARE( vertices.constGet()->partCount(), 4 ); - QCOMPARE( vertices.constGet()->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( 0, -0.87614105022163979 ) ); + QCOMPARE( vertices.constGet()->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( 0, -2.45319494062059196 ) ); QCOMPARE( vertices.constGet()->vertexAt( QgsVertexId( 1, 0, 0 ) ), QgsPoint( 0, 0.5 ) ); QCOMPARE( vertices.constGet()->vertexAt( QgsVertexId( 2, 0, 0 ) ), QgsPoint( 0.5, 1 ) ); - QCOMPARE( vertices.constGet()->vertexAt( QgsVertexId( 3, 0, 0 ) ), QgsPoint( 1.87040839992228825, 1 ) ); + QCOMPARE( vertices.constGet()->vertexAt( QgsVertexId( 3, 0, 0 ) ), QgsPoint( 3.43714351978240718, 1 ) ); // multipoint QgsVectorLayer *pointLayer = new QgsVectorLayer( QStringLiteral( "MultiPoint?crs=epsg:4326" ), QString(), QStringLiteral( "memory" ) ); @@ -632,14 +632,14 @@ void TestMapTools::testHandles() // an existing vertex (start/end of the line) QVector expected = { - QStringLiteral( "LineString (0 -0.87614105022164, 0 0)" ), - QStringLiteral( "LineString (1 1, 1.87040839992229 1)" ), + QStringLiteral( "LineString (0 -2.45319494062059, 0 0)" ), + QStringLiteral( "LineString (1 1, 3.43714351978241 1)" ), }; const QVector parts = handles.asGeometryCollection(); for ( int i = 0; i < parts.count(); i++ ) { - QVERIFY( parts.at( i ).asWkt( 14 ) == expected.at( i ) ); + QCOMPARE( parts.at( i ).asWkt( 14 ), expected.at( i ) ); } delete lineLayer; @@ -678,7 +678,7 @@ void TestMapTools::testLookForVertex() QCOMPARE( mapTool.state(), RecordingMapTool::MapToolState::View ); // Start handle point. Active vertex is invalid, state changes to Record - QPointF screenPoint = ms->coordinateToScreen( QgsPoint( -0.05, -0.83 ) ); + QPointF screenPoint = ms->coordinateToScreen( QgsPoint( -0.05, -2.45 ) ); mapTool.lookForVertex( screenPoint ); QVERIFY( !mapTool.activeVertex().isValid() ); QCOMPARE( mapTool.state(), RecordingMapTool::MapToolState::Record ); @@ -1038,7 +1038,7 @@ void TestMapTools::testAddVertexLineLayer() mapTool.addPoint( pointsToAdd[1] ); - QCOMPARE( mapTool.handles().vertexAt( 0 ).asWkt( 14 ), "Point (-96.22182942132511 22.34151145046518)" ); + QCOMPARE( mapTool.handles().vertexAt( 0 ).asWkt( 14 ), "Point (-94.5889223797103 21.87263206130249)" ); QCOMPARE( mapTool.handles().vertexAt( 1 ), pointsToAdd[0] ); delete project;