Compare commits

...

17 Commits

Author SHA1 Message Date
qgis-bot
dd89ba5fbf
Merge c19416bb78a666ea85e8d897e8973dc4a52627e5 into 1fc67c60090cc195629a95af92e9f4333b4254a2 2025-10-02 09:53:25 +10:00
Mathieu Pellerin
1fc67c6009 Add libspatialindex port to pin version 2.0 until further notice 2025-10-01 18:15:21 +10:00
Nyall Dawson
070c13e4ab Block building on spatialindex >= 2.1
See https://github.com/libspatialindex/libspatialindex/issues/276,
this is silently giving misleading results
2025-10-01 18:15:21 +10:00
Nyall Dawson
01c86da6a4 Catch some more exceptions from libspatialindex 2025-10-01 18:15:21 +10:00
Nyall Dawson
6a3cd87737 Fixing missing arg marker when exception occurs in spatial index 2025-10-01 18:15:21 +10:00
Nyall Dawson
4cab2daf50 Update src/gui/processing/qgsprocessingoutputdestinationwidget.cpp 2025-10-01 16:03:18 +10:00
Alexander Bruy
33cba935d2 change default folder for Processing outputs to $HOME/processing to make
it more visible and accessible
2025-10-01 16:03:18 +10:00
Alexander Bruy
62830e0412 provide default value when reading output folder setting to generate
destination path in Processing (fix #61965)
2025-10-01 16:03:18 +10:00
Alexander Bruy
b046379b51
Merge pull request #63379 from qgis/backport-63355-to-release-3_44
[Backport release-3_44] [themes][ui] Fix color for selected tree widget items, when they are disabled
2025-09-30 06:48:47 +01:00
Alexander Bruy
086dd9bc36
Merge pull request #63367 from qgis/backport-63240-to-release-3_44
[Backport release-3_44] processing: Call gdal_merge instead of gdal_merge.py
2025-09-30 06:46:16 +01:00
Malik Blesius
dd856e8cb0 [themes][ui] Fix color for selected tree widget items, when they are also disabled for dark themes 2025-09-29 23:02:39 +00:00
Nyall Dawson
b21b0bcd4c Use gdal_merge.py for GDAL < 3.9 2025-09-29 12:04:39 +00:00
Nyall Dawson
2a2ba2b6df Update tests 2025-09-29 12:04:39 +00:00
Aleix Pol
360d025063 processing: Call gdal_merge instead of gdal_merge.py
The latter is deprecated by gdal and it has a bogus shebang.
2025-09-29 12:04:39 +00:00
Nyall Dawson
c19416bb78
[vertextool] Interpolate Z/M when adding vertex to segment
When adding a vertex in the middle of a segment with valid
Z or M values at the neighbouring vertices, interpolate the
new vertex Z / M value from these neighbouring Z / M values.

Fixes #57819
2025-09-12 09:09:18 +10:00
Nyall Dawson
5980bbd077
Add vertex tool tests for adding vertices to layer with M 2025-09-12 09:09:18 +10:00
Nyall Dawson
34d20c54f5
Add unit tests for vertex editor adding vertices to z enabled layer 2025-09-12 09:09:18 +10:00
14 changed files with 369 additions and 18 deletions

View File

@ -451,6 +451,9 @@ if(WITH_CORE)
message(STATUS "Found GDAL: ${GDAL_VERSION} ${GDAL_DIR}") message(STATUS "Found GDAL: ${GDAL_VERSION} ${GDAL_DIR}")
find_package(EXPAT REQUIRED) find_package(EXPAT REQUIRED)
find_package(Spatialindex REQUIRED) find_package(Spatialindex REQUIRED)
if(SPATIALINDEX_VERSION VERSION_GREATER_EQUAL "2.1")
message(FATAL_ERROR "Cannot build QGIS using libspatialindex >= 2.1, see https://github.com/libspatialindex/libspatialindex/issues/276")
endif()
find_package(LibZip REQUIRED) find_package(LibZip REQUIRED)
set (WITH_INTERNAL_NLOHMANN_JSON ${PREFER_INTERNAL_LIBS} CACHE BOOL "Determines whether the vendored copy of nlohmann-json should be used") set (WITH_INTERNAL_NLOHMANN_JSON ${PREFER_INTERNAL_LIBS} CACHE BOOL "Determines whether the vendored copy of nlohmann-json should be used")
find_package(nlohmann_json REQUIRED) find_package(nlohmann_json REQUIRED)

View File

@ -8,7 +8,7 @@
# SPATIALINDEX_FOUND = system has Spatialindex lib # SPATIALINDEX_FOUND = system has Spatialindex lib
# SPATIALINDEX_LIBRARY = full path to the Spatialindex library # SPATIALINDEX_LIBRARY = full path to the Spatialindex library
# SPATIALINDEX_INCLUDE_DIR = where to find headers # SPATIALINDEX_INCLUDE_DIR = where to find headers
# # SPATIALINDEX_VERSION = version number
FIND_PATH(SPATIALINDEX_INCLUDE_DIR spatialindex/SpatialIndex.h PATHS FIND_PATH(SPATIALINDEX_INCLUDE_DIR spatialindex/SpatialIndex.h PATHS
@ -32,8 +32,21 @@ IF (SPATIALINDEX_INCLUDE_DIR AND SPATIALINDEX_LIBRARY)
ENDIF (SPATIALINDEX_INCLUDE_DIR AND SPATIALINDEX_LIBRARY) ENDIF (SPATIALINDEX_INCLUDE_DIR AND SPATIALINDEX_LIBRARY)
IF (SPATIALINDEX_FOUND) IF (SPATIALINDEX_FOUND)
set(spatialindex_version_file
"${SPATIALINDEX_INCLUDE_DIR}/spatialindex/Version.h")
file(STRINGS "${spatialindex_version_file}" spatialindex_version_major REGEX "#define SIDX_VERSION_MAJOR")
list(GET spatialindex_version_major 0 spatialindex_version_major)
string(REGEX MATCH "[0-9]+" SPATIALINDEX_VERSION_MAJOR ${spatialindex_version_major} )
file(STRINGS "${spatialindex_version_file}" spatialindex_version_minor REGEX "#define SIDX_VERSION_MINOR")
list(GET spatialindex_version_minor 0 spatialindex_version_minor)
string(REGEX MATCH "[0-9]+" SPATIALINDEX_VERSION_MINOR ${spatialindex_version_minor} )
file(STRINGS "${spatialindex_version_file}" spatialindex_version_rev REGEX "#define SIDX_VERSION_REV")
list(GET spatialindex_version_rev 0 spatialindex_version_rev)
string(REGEX MATCH "[0-9]+" SPATIALINDEX_VERSION_REV ${spatialindex_version_rev} )
set(SPATIALINDEX_VERSION "${SPATIALINDEX_VERSION_MAJOR}.${SPATIALINDEX_VERSION_MINOR}.${SPATIALINDEX_VERSION_REV}")
IF (NOT SPATIALINDEX_FIND_QUIETLY) IF (NOT SPATIALINDEX_FIND_QUIETLY)
MESSAGE(STATUS "Found Spatialindex: ${SPATIALINDEX_LIBRARY}") MESSAGE(STATUS "Found Spatialindex: ${SPATIALINDEX_LIBRARY} (${SPATIALINDEX_VERSION})")
ENDIF (NOT SPATIALINDEX_FIND_QUIETLY) ENDIF (NOT SPATIALINDEX_FIND_QUIETLY)
ELSE (SPATIALINDEX_FOUND) ELSE (SPATIALINDEX_FOUND)
IF (SPATIALINDEX_FIND_REQUIRED) IF (SPATIALINDEX_FIND_REQUIRED)

View File

@ -266,6 +266,19 @@ class merge(GdalAlgorithm):
arguments.append(list_file) arguments.append(list_file)
return [ return [
self.commandName() + (".bat" if isWindows() else ".py"), self.commandName() + merge.command_ext(),
GdalUtils.escapeAndJoin(arguments), GdalUtils.escapeAndJoin(arguments),
] ]
@staticmethod
def command_ext() -> str:
"""
Returns the gdal_merge command extension
"""
if isWindows():
return ".bat"
if GdalUtils.version() < 3090000:
return ".py"
return ""

View File

@ -4556,6 +4556,8 @@ class TestGdalRasterAlgorithms(QgisTestCase, AlgorithmsTestBase.AlgorithmsTest):
alg = merge() alg = merge()
alg.initAlgorithm() alg.initAlgorithm()
merge_command = alg.commandName() + alg.command_ext()
with tempfile.TemporaryDirectory() as outdir: with tempfile.TemporaryDirectory() as outdir:
# this algorithm creates temporary text file with input layers # this algorithm creates temporary text file with input layers
# so we strip its path, leaving only filename # so we strip its path, leaving only filename
@ -4567,7 +4569,7 @@ class TestGdalRasterAlgorithms(QgisTestCase, AlgorithmsTestBase.AlgorithmsTest):
self.assertEqual( self.assertEqual(
cmd, cmd,
[ [
"gdal_merge.py", merge_command,
"-ot Float32 -of GTiff " "-ot Float32 -of GTiff "
+ "-o " + "-o "
+ outdir + outdir
@ -4586,7 +4588,7 @@ class TestGdalRasterAlgorithms(QgisTestCase, AlgorithmsTestBase.AlgorithmsTest):
self.assertEqual( self.assertEqual(
cmd, cmd,
[ [
"gdal_merge.py", merge_command,
"-separate -ot Float32 -of GTiff " "-separate -ot Float32 -of GTiff "
+ "-o " + "-o "
+ outdir + outdir
@ -4610,7 +4612,7 @@ class TestGdalRasterAlgorithms(QgisTestCase, AlgorithmsTestBase.AlgorithmsTest):
self.assertEqual( self.assertEqual(
cmd, cmd,
[ [
"gdal_merge.py", merge_command,
"-ot Float32 -of GTiff -tap -ps 0.1 0.1 " "-ot Float32 -of GTiff -tap -ps 0.1 0.1 "
+ "-o " + "-o "
+ outdir + outdir
@ -4634,7 +4636,7 @@ class TestGdalRasterAlgorithms(QgisTestCase, AlgorithmsTestBase.AlgorithmsTest):
self.assertEqual( self.assertEqual(
cmd, cmd,
[ [
"gdal_merge.py", merge_command,
"-a_nodata -9999.0 -ot Float32 -of GTiff " "-a_nodata -9999.0 -ot Float32 -of GTiff "
+ "-o " + "-o "
+ outdir + outdir

View File

@ -41,7 +41,7 @@ def userFolder():
def defaultOutputFolder(): def defaultOutputFolder():
folder = os.path.join(userFolder(), "outputs") folder = os.path.join(QDir.homePath(), "processing")
if not QDir(folder).exists(): if not QDir(folder).exists():
QDir().mkpath(folder) QDir().mkpath(folder)

View File

@ -988,6 +988,11 @@ QTreeView::item:selected, QTreeView::branch:selected {
color: @text; color: @text;
} }
QTreeView::item:selected:disabled, QTreeView::branch:selected:disabled {
background-color: @itemalternativebackground;
color: @background;
}
QTreeView::branch:has-children:!has-siblings:closed, QTreeView::branch:has-children:!has-siblings:closed,
QTreeView::branch:closed:has-children:has-siblings { QTreeView::branch:closed:has-children:has-siblings {
border-image: none; border-image: none;

View File

@ -1019,6 +1019,11 @@ QTreeView::item:selected, QTreeView::branch:selected {
color: @textlight; color: @textlight;
} }
QTreeView::item:selected:disabled, QTreeView::branch:selected:disabled {
background-color: @itemdarkbackground;
color: @background;
}
QTreeView::branch:has-children:!has-siblings:closed, QTreeView::branch:has-children:!has-siblings:closed,
QTreeView::branch:closed:has-children:has-siblings { QTreeView::branch:closed:has-children:has-siblings {
border-image: none; border-image: none;

View File

@ -2165,10 +2165,46 @@ void QgsVertexTool::moveVertex( const QgsPointXY &mapPoint, const QgsPointLocato
QgsPoint pt( layerPoint ); QgsPoint pt( layerPoint );
if ( QgsWkbTypes::hasZ( dragLayer->wkbType() ) && !pt.is3D() ) if ( QgsWkbTypes::hasZ( dragLayer->wkbType() ) && !pt.is3D() )
{
pt.addZValue( defaultZValue() ); pt.addZValue( defaultZValue() );
if ( !addingAtEndpoint )
{
// try to linearly interpolate z from adjacent vertices
const QgsPoint pointBefore = geomTmp->vertexAt( QgsVertexId( vid.part, vid.ring, vid.vertex - 1 ) );
const QgsPoint pointAfter = geomTmp->vertexAt( vid );
// we can only do this if the adjacent vertices HAVE valid z values
if ( !std::isnan( pointBefore.z() ) && !std::isnan( pointAfter.z() ) )
{
const double distanceFromFirstVertexToNewVertex = pointBefore.distance( pt );
const double newDistanceBetweenOriginalAdjacentVertices = distanceFromFirstVertexToNewVertex + pt.distance( pointAfter );
if ( newDistanceBetweenOriginalAdjacentVertices )
{
pt.setZ( pointBefore.z() + ( pointAfter.z() - pointBefore.z() ) * distanceFromFirstVertexToNewVertex / newDistanceBetweenOriginalAdjacentVertices );
}
}
}
}
if ( QgsWkbTypes::hasM( dragLayer->wkbType() ) && !pt.isMeasure() ) if ( QgsWkbTypes::hasM( dragLayer->wkbType() ) && !pt.isMeasure() )
{
pt.addMValue( defaultMValue() ); pt.addMValue( defaultMValue() );
if ( !addingAtEndpoint )
{
// try to linearly interpolate m from adjacent vertices
const QgsPoint pointBefore = geomTmp->vertexAt( QgsVertexId( vid.part, vid.ring, vid.vertex - 1 ) );
const QgsPoint pointAfter = geomTmp->vertexAt( vid );
// we can only do this if the adjacent vertices HAVE valid m values
if ( !std::isnan( pointBefore.m() ) && !std::isnan( pointAfter.m() ) )
{
const double distanceFromFirstVertexToNewVertex = pointBefore.distance( pt );
const double newDistanceBetweenOriginalAdjacentVertices = distanceFromFirstVertexToNewVertex + pt.distance( pointAfter );
if ( newDistanceBetweenOriginalAdjacentVertices )
{
pt.setM( pointBefore.m() + ( pointAfter.m() - pointBefore.m() ) * distanceFromFirstVertexToNewVertex / newDistanceBetweenOriginalAdjacentVertices );
}
}
}
}
if ( !geomTmp->insertVertex( vid, pt ) ) if ( !geomTmp->insertVertex( vid, pt ) )
{ {

View File

@ -77,16 +77,16 @@ class QgsGenericSpatialIndex
catch ( Tools::Exception &e ) catch ( Tools::Exception &e )
{ {
Q_UNUSED( e ) Q_UNUSED( e )
QgsDebugError( QStringLiteral( "Tools::Exception caught: " ).arg( e.what().c_str() ) ); QgsDebugError( QStringLiteral( "Tools::Exception caught when inserting data to QgsGenericSpatialIndex: %1" ).arg( e.what().c_str() ) );
} }
catch ( const std::exception &e ) catch ( const std::exception &e )
{ {
Q_UNUSED( e ) Q_UNUSED( e )
QgsDebugError( QStringLiteral( "std::exception caught: " ).arg( e.what() ) ); QgsDebugError( QStringLiteral( "std::exception caught when inserting data to QgsGenericSpatialIndex: %1" ).arg( e.what() ) );
} }
catch ( ... ) catch ( ... )
{ {
QgsDebugError( QStringLiteral( "unknown spatial index exception caught" ) ); QgsDebugError( QStringLiteral( "unknown spatial index exception caught when inserting data to QgsGenericSpatialIndex" ) );
} }
return false; return false;
@ -126,7 +126,25 @@ class QgsGenericSpatialIndex
const SpatialIndex::Region r = QgsSpatialIndexUtils::rectangleToRegion( bounds ); const SpatialIndex::Region r = QgsSpatialIndexUtils::rectangleToRegion( bounds );
const QMutexLocker locker( &mMutex ); const QMutexLocker locker( &mMutex );
try
{
mRTree->intersectsWithQuery( r, visitor ); mRTree->intersectsWithQuery( r, visitor );
}
catch ( Tools::Exception &e )
{
Q_UNUSED( e )
QgsDebugError( QStringLiteral( "Tools::Exception caught in QgsGenericSpatialIndex::intersects: %1" ).arg( e.what().c_str() ) );
}
catch ( const std::exception &e )
{
Q_UNUSED( e )
QgsDebugError( QStringLiteral( "std::exception caught in QgsGenericSpatialIndex::intersects: %1" ).arg( e.what() ) );
}
catch ( ... )
{
QgsDebugError( QStringLiteral( "unknown spatial index exception caught in QgsGenericSpatialIndex::intersects" ) );
}
return true; return true;
} }

View File

@ -457,16 +457,16 @@ bool QgsSpatialIndex::addFeature( QgsFeatureId id, const QgsRectangle &bounds )
catch ( Tools::Exception &e ) catch ( Tools::Exception &e )
{ {
Q_UNUSED( e ) Q_UNUSED( e )
QgsDebugError( QStringLiteral( "Tools::Exception caught: " ).arg( e.what().c_str() ) ); QgsDebugError( QStringLiteral( "Tools::Exception caught when adding feature to QgsSpatialIndex: %1" ).arg( e.what().c_str() ) );
} }
catch ( const std::exception &e ) catch ( const std::exception &e )
{ {
Q_UNUSED( e ) Q_UNUSED( e )
QgsDebugError( QStringLiteral( "std::exception caught: " ).arg( e.what() ) ); QgsDebugError( QStringLiteral( "std::exception caught when adding feature to QgsSpatialIndex: %1" ).arg( e.what() ) );
} }
catch ( ... ) catch ( ... )
{ {
QgsDebugError( QStringLiteral( "unknown spatial index exception caught" ) ); QgsDebugError( QStringLiteral( "unknown spatial index exception caught when adding feature to QgsSpatialIndex" ) );
} }
return false; return false;

View File

@ -25,6 +25,7 @@
#include "qgsprocessingcontext.h" #include "qgsprocessingcontext.h"
#include "qgsprocessingalgorithm.h" #include "qgsprocessingalgorithm.h"
#include "qgsfieldmappingwidget.h" #include "qgsfieldmappingwidget.h"
#include "qgsapplication.h"
#include <QMenu> #include <QMenu>
#include <QFileDialog> #include <QFileDialog>
#include <QInputDialog> #include <QInputDialog>
@ -175,7 +176,7 @@ QVariant QgsProcessingLayerOutputDestinationWidget::value() const
if ( folder == '.' ) if ( folder == '.' )
{ {
// output name does not include a folder - use default // output name does not include a folder - use default
QString defaultFolder = settings.value( QStringLiteral( "/Processing/Configuration/OUTPUTS_FOLDER" ) ).toString(); QString defaultFolder = settings.value( QStringLiteral( "/Processing/Configuration/OUTPUTS_FOLDER" ), QStringLiteral( "%1/processing" ).arg( QDir::homePath() ) ).toString();
key = QDir( defaultFolder ).filePath( key ); key = QDir( defaultFolder ).filePath( key );
} }
} }

View File

@ -77,6 +77,8 @@ class TestQgsVertexTool : public QObject
void testAddVertexAtEndpoint(); void testAddVertexAtEndpoint();
void testAddVertexDoubleClick(); void testAddVertexDoubleClick();
void testAddVertexDoubleClickWithShift(); void testAddVertexDoubleClickWithShift();
void testAddVertexZ();
void testAddVertexM();
void testAvoidIntersections(); void testAvoidIntersections();
void testDeleteVertex(); void testDeleteVertex();
void testConvertVertex(); void testConvertVertex();
@ -165,11 +167,14 @@ class TestQgsVertexTool : public QObject
QPointer< QgsVectorLayer > mLayerPoint; QPointer< QgsVectorLayer > mLayerPoint;
QPointer< QgsVectorLayer > mLayerPointZ; QPointer< QgsVectorLayer > mLayerPointZ;
QPointer< QgsVectorLayer > mLayerLineZ; QPointer< QgsVectorLayer > mLayerLineZ;
QPointer< QgsVectorLayer > mLayerLineM;
QPointer< QgsVectorLayer > mLayerCompoundCurve; QPointer< QgsVectorLayer > mLayerCompoundCurve;
QPointer< QgsVectorLayer > mLayerLineReprojected; QPointer< QgsVectorLayer > mLayerLineReprojected;
QgsFeatureId mFidLineZF1 = 0; QgsFeatureId mFidLineZF1 = 0;
QgsFeatureId mFidLineZF2 = 0; QgsFeatureId mFidLineZF2 = 0;
QgsFeatureId mFidLineZF3 = 0; QgsFeatureId mFidLineZF3 = 0;
QgsFeatureId mFidLineMF1 = 0;
QgsFeatureId mFidLineMF2 = 0;
QgsFeatureId mFidLineF1 = 0; QgsFeatureId mFidLineF1 = 0;
QgsFeatureId mFidMultiLineF1 = 0; QgsFeatureId mFidMultiLineF1 = 0;
QgsFeatureId mFidLineF13857 = 0; QgsFeatureId mFidLineF13857 = 0;
@ -236,10 +241,13 @@ void TestQgsVertexTool::init()
mLayerLineZ = new QgsVectorLayer( QStringLiteral( "LineStringZ?" ), QStringLiteral( "layer line z" ), QStringLiteral( "memory" ) ); mLayerLineZ = new QgsVectorLayer( QStringLiteral( "LineStringZ?" ), QStringLiteral( "layer line z" ), QStringLiteral( "memory" ) );
QVERIFY( mLayerLineZ->isValid() ); QVERIFY( mLayerLineZ->isValid() );
mLayerLineZ->setCrs( mFake27700 ); mLayerLineZ->setCrs( mFake27700 );
mLayerLineM = new QgsVectorLayer( QStringLiteral( "LineStringM?" ), QStringLiteral( "layer line m" ), QStringLiteral( "memory" ) );
QVERIFY( mLayerLineM->isValid() );
mLayerLineM->setCrs( mFake27700 );
mLayerCompoundCurve = new QgsVectorLayer( QStringLiteral( "CompoundCurve?" ), QStringLiteral( "layer compound curve" ), QStringLiteral( "memory" ) ); mLayerCompoundCurve = new QgsVectorLayer( QStringLiteral( "CompoundCurve?" ), QStringLiteral( "layer compound curve" ), QStringLiteral( "memory" ) );
QVERIFY( mLayerCompoundCurve->isValid() ); QVERIFY( mLayerCompoundCurve->isValid() );
mLayerCompoundCurve->setCrs( mFake27700 ); mLayerCompoundCurve->setCrs( mFake27700 );
QgsProject::instance()->addMapLayers( QList<QgsMapLayer *>() << mLayerLine << mLayerMultiLine << mLayerPolygon << mLayerMultiPolygon << mLayerPoint << mLayerPointZ << mLayerLineZ << mLayerCompoundCurve ); QgsProject::instance()->addMapLayers( QList<QgsMapLayer *>() << mLayerLine << mLayerMultiLine << mLayerPolygon << mLayerMultiPolygon << mLayerPoint << mLayerPointZ << mLayerLineZ << mLayerLineM << mLayerCompoundCurve );
QgsFeature lineF1; QgsFeature lineF1;
@ -271,6 +279,10 @@ void TestQgsVertexTool::init()
linez2.setGeometry( QgsGeometry::fromWkt( "LineStringZ (5 7 5, 7 7 10)" ) ); linez2.setGeometry( QgsGeometry::fromWkt( "LineStringZ (5 7 5, 7 7 10)" ) );
linez3.setGeometry( QgsGeometry::fromWkt( "LineStringZ (5 5.5 5, 7 5.5 10)" ) ); linez3.setGeometry( QgsGeometry::fromWkt( "LineStringZ (5 5.5 5, 7 5.5 10)" ) );
QgsFeature linem1, linem2;
linem1.setGeometry( QgsGeometry::fromWkt( "LineStringM (5 5 1, 6 6 1, 7 5 1)" ) );
linem2.setGeometry( QgsGeometry::fromWkt( "LineStringM (5 7 5, 7 7 10)" ) );
QgsFeature curveF1; QgsFeature curveF1;
curveF1.setGeometry( QgsGeometry::fromWkt( "CompoundCurve (CircularString (14 14, 10 10, 17 10))" ) ); curveF1.setGeometry( QgsGeometry::fromWkt( "CompoundCurve (CircularString (14 14, 10 10, 17 10))" ) );
QgsFeature curveF2; QgsFeature curveF2;
@ -321,6 +333,17 @@ void TestQgsVertexTool::init()
mFidLineZF3 = linez3.id(); mFidLineZF3 = linez3.id();
QCOMPARE( mLayerLineZ->featureCount(), ( long ) 3 ); QCOMPARE( mLayerLineZ->featureCount(), ( long ) 3 );
mLayerLineM->dataProvider()->addFeature( linem1 );
mFidLineMF1 = linem1.id();
mLayerLineM->dataProvider()->addFeature( linem2 );
mFidLineMF2 = linem2.id();
QCOMPARE( mLayerLineM->featureCount(), ( long ) 2 );
mFidLineZF1 = linez1.id();
mFidLineZF2 = linez2.id();
mFidLineZF3 = linez3.id();
QCOMPARE( mLayerLineZ->featureCount(), ( long ) 3 );
mLayerCompoundCurve->startEditing(); mLayerCompoundCurve->startEditing();
mLayerCompoundCurve->addFeature( curveF1 ); mLayerCompoundCurve->addFeature( curveF1 );
mLayerCompoundCurve->addFeature( curveF2 ); mLayerCompoundCurve->addFeature( curveF2 );
@ -355,7 +378,7 @@ void TestQgsVertexTool::init()
QCOMPARE( mCanvas->mapSettings().outputSize(), QSize( 512, 512 ) ); QCOMPARE( mCanvas->mapSettings().outputSize(), QSize( 512, 512 ) );
QCOMPARE( mCanvas->mapSettings().visibleExtent(), QgsRectangle( 0, 0, 8, 8 ) ); QCOMPARE( mCanvas->mapSettings().visibleExtent(), QgsRectangle( 0, 0, 8, 8 ) );
mCanvas->setLayers( QList<QgsMapLayer *>() << mLayerLine << mLayerMultiLine << mLayerLineReprojected << mLayerPolygon << mLayerMultiPolygon << mLayerPoint << mLayerPointZ << mLayerLineZ << mLayerCompoundCurve ); mCanvas->setLayers( QList<QgsMapLayer *>() << mLayerLine << mLayerMultiLine << mLayerLineReprojected << mLayerPolygon << mLayerMultiPolygon << mLayerPoint << mLayerPointZ << mLayerLineZ << mLayerLineM << mLayerCompoundCurve );
QgsMapCanvasSnappingUtils *snappingUtils = new QgsMapCanvasSnappingUtils( mCanvas, this ); QgsMapCanvasSnappingUtils *snappingUtils = new QgsMapCanvasSnappingUtils( mCanvas, this );
mCanvas->setSnappingUtils( snappingUtils ); mCanvas->setSnappingUtils( snappingUtils );
@ -368,6 +391,7 @@ void TestQgsVertexTool::init()
snappingUtils->locatorForLayer( mLayerPoint )->init(); snappingUtils->locatorForLayer( mLayerPoint )->init();
snappingUtils->locatorForLayer( mLayerPointZ )->init(); snappingUtils->locatorForLayer( mLayerPointZ )->init();
snappingUtils->locatorForLayer( mLayerLineZ )->init(); snappingUtils->locatorForLayer( mLayerLineZ )->init();
snappingUtils->locatorForLayer( mLayerLineM )->init();
snappingUtils->locatorForLayer( mLayerCompoundCurve )->init(); snappingUtils->locatorForLayer( mLayerCompoundCurve )->init();
// create vertex tool // create vertex tool
@ -730,6 +754,193 @@ void TestQgsVertexTool::testAddVertex()
QCOMPARE( mLayerPoint->undoStack()->index(), 1 ); QCOMPARE( mLayerPoint->undoStack()->index(), 1 );
} }
void TestQgsVertexTool::testAddVertexZ()
{
QgsSettingsRegistryCore::settingsDigitizingDefaultZValue->setValue( 333 );
// add vertex in linestringZ
QCOMPARE( mLayerLineZ->undoStack()->index(), 3 );
// in middle of segment
mouseClick( 6.5, 5.5, Qt::LeftButton );
QCOMPARE( mVertexTool->mDraggingVertexType, QgsVertexTool::DraggingVertexType::AddingVertex );
QCOMPARE( mVertexTool->mDraggingVertex->layer->id(), mLayerLineZ->id() );
QCOMPARE( mVertexTool->mDraggingVertex->fid, mFidLineZF1 );
QCOMPARE( mVertexTool->mDraggingVertex->vertexId, 2 );
mouseClick( 7, 6, Qt::LeftButton );
QCOMPARE( mLayerLineZ->undoStack()->index(), 4 );
// when adding a vertex in the middle of an existing segment with z values, the z value should be linearly interpolated
QCOMPARE( mLayerLineZ->getFeature( mFidLineZF1 ).geometry().asWkt( 1 ), QStringLiteral( "LineString Z (5 5 1, 6 6 1, 7 6 1, 7 5 1)" ) );
mLayerLineZ->undoStack()->undo();
QCOMPARE( mLayerLineZ->undoStack()->index(), 3 );
QCOMPARE( mLayerLineZ->getFeature( mFidLineZF1 ).geometry().asWkt( 1 ), QStringLiteral( "LineString Z (5 5 1, 6 6 1, 7 5 1)" ) );
mouseClick( 6, 7, Qt::LeftButton );
QCOMPARE( mVertexTool->mDraggingVertexType, QgsVertexTool::DraggingVertexType::AddingVertex );
QCOMPARE( mVertexTool->mDraggingVertex->layer->id(), mLayerLineZ->id() );
QCOMPARE( mVertexTool->mDraggingVertex->fid, mFidLineZF2 );
QCOMPARE( mVertexTool->mDraggingVertex->vertexId, 1 );
mouseClick( 5, 7.5, Qt::LeftButton );
QCOMPARE( mLayerLineZ->undoStack()->index(), 4 );
// when adding a vertex in the middle of an existing segment with z values, the z value should be linearly interpolated
QCOMPARE( mLayerLineZ->getFeature( mFidLineZF2 ).geometry().asWkt( 1 ), QStringLiteral( "LineString Z (5 7 5, 5 7.5 6, 7 7 10)" ) );
mLayerLineZ->undoStack()->undo();
QCOMPARE( mLayerLineZ->undoStack()->index(), 3 );
QCOMPARE( mLayerLineZ->getFeature( mFidLineZF2 ).geometry().asWkt( 1 ), QStringLiteral( "LineString Z (5 7 5, 7 7 10)" ) );
// inserting vertex via double-click
mouseDoubleClick( 5.2, 5.2, Qt::LeftButton );
QCOMPARE( mVertexTool->mDraggingVertexType, QgsVertexTool::DraggingVertexType::AddingVertex );
QCOMPARE( mVertexTool->mDraggingVertex->layer->id(), mLayerLineZ->id() );
QCOMPARE( mVertexTool->mDraggingVertex->fid, mFidLineZF1 );
QCOMPARE( mVertexTool->mDraggingVertex->vertexId, 1 );
mouseClick( 5, 5.5, Qt::LeftButton );
QCOMPARE( mLayerLineZ->undoStack()->index(), 4 );
QCOMPARE( mLayerLineZ->getFeature( mFidLineZF1 ).geometry().asWkt( 1 ), QStringLiteral( "LineString Z (5 5 1, 5 5.5 1, 6 6 1, 7 5 1)" ) );
mLayerLineZ->undoStack()->undo();
QCOMPARE( mLayerLineZ->undoStack()->index(), 3 );
QCOMPARE( mLayerLineZ->getFeature( mFidLineZF1 ).geometry().asWkt( 1 ), QStringLiteral( "LineString Z (5 5 1, 6 6 1, 7 5 1)" ) );
mouseDoubleClick( 5.3, 7, Qt::LeftButton );
QCOMPARE( mVertexTool->mDraggingVertexType, QgsVertexTool::DraggingVertexType::AddingVertex );
QCOMPARE( mVertexTool->mDraggingVertex->layer->id(), mLayerLineZ->id() );
QCOMPARE( mVertexTool->mDraggingVertex->fid, mFidLineZF2 );
QCOMPARE( mVertexTool->mDraggingVertex->vertexId, 1 );
mouseClick( 5, 7.5, Qt::LeftButton );
QCOMPARE( mLayerLineZ->undoStack()->index(), 4 );
QCOMPARE( mLayerLineZ->getFeature( mFidLineZF2 ).geometry().asWkt( 1 ), QStringLiteral( "LineString Z (5 7 5, 5 7.5 6, 7 7 10)" ) );
mLayerLineZ->undoStack()->undo();
QCOMPARE( mLayerLineZ->undoStack()->index(), 3 );
QCOMPARE( mLayerLineZ->getFeature( mFidLineZF2 ).geometry().asWkt( 1 ), QStringLiteral( "LineString Z (5 7 5, 7 7 10)" ) );
// insert vertex at endpoint -- the default z value should be used
// offset of the endpoint marker - currently set as 15px away from the last vertex in direction of the line
const double offsetInMapUnits = 15 * mCanvas->mapSettings().mapUnitsPerPixel();
mouseMove( 5, 5 ); // first we need to move to the vertex
mouseClick( 5 - offsetInMapUnits / M_SQRT2, 5 - offsetInMapUnits / M_SQRT2, Qt::LeftButton );
QCOMPARE( mVertexTool->mDraggingVertexType, QgsVertexTool::DraggingVertexType::AddingEndpoint );
QCOMPARE( mVertexTool->mDraggingVertex->layer->id(), mLayerLineZ->id() );
QCOMPARE( mVertexTool->mDraggingVertex->fid, mFidLineZF1 );
QCOMPARE( mVertexTool->mDraggingVertex->vertexId, 0 );
mouseClick( 5, 4, Qt::LeftButton );
QCOMPARE( mLayerLineZ->undoStack()->index(), 4 );
QCOMPARE( mLayerLineZ->getFeature( mFidLineZF1 ).geometry().asWkt( 1 ), QStringLiteral( "LineString Z (5 4 333, 5 5 1, 6 6 1, 7 5 1)" ) );
mLayerLineZ->undoStack()->undo();
QCOMPARE( mLayerLineZ->undoStack()->index(), 3 );
QCOMPARE( mLayerLineZ->getFeature( mFidLineZF1 ).geometry().asWkt( 1 ), QStringLiteral( "LineString Z (5 5 1, 6 6 1, 7 5 1)" ) );
}
void TestQgsVertexTool::testAddVertexM()
{
QgsSettingsRegistryCore::settingsDigitizingDefaultMValue->setValue( 222 );
// add vertex in linestringM
// ensure changes are made to mLayerLineZ
mLayerLineM->startEditing();
mLayerLineZ->commitChanges();
QCOMPARE( mLayerLineM->undoStack()->index(), 0 );
// in middle of segment
mouseClick( 6.5, 5.5, Qt::LeftButton );
QCOMPARE( mVertexTool->mDraggingVertexType, QgsVertexTool::DraggingVertexType::AddingVertex );
QCOMPARE( mVertexTool->mDraggingVertex->layer->id(), mLayerLineM->id() );
QCOMPARE( mVertexTool->mDraggingVertex->fid, mFidLineMF1 );
QCOMPARE( mVertexTool->mDraggingVertex->vertexId, 2 );
mouseClick( 7, 6, Qt::LeftButton );
QCOMPARE( mLayerLineM->undoStack()->index(), 1 );
// when adding a vertex in the middle of an existing segment with m values, the m value should be linearly interpolated
QCOMPARE( mLayerLineM->getFeature( mFidLineMF1 ).geometry().asWkt( 1 ), QStringLiteral( "LineString M (5 5 1, 6 6 1, 7 6 1, 7 5 1)" ) );
mLayerLineM->undoStack()->undo();
QCOMPARE( mLayerLineM->undoStack()->index(), 0 );
QCOMPARE( mLayerLineM->getFeature( mFidLineMF1 ).geometry().asWkt( 1 ), QStringLiteral( "LineString M (5 5 1, 6 6 1, 7 5 1)" ) );
mouseClick( 6, 7, Qt::LeftButton );
QCOMPARE( mVertexTool->mDraggingVertexType, QgsVertexTool::DraggingVertexType::AddingVertex );
QCOMPARE( mVertexTool->mDraggingVertex->layer->id(), mLayerLineM->id() );
QCOMPARE( mVertexTool->mDraggingVertex->fid, mFidLineMF2 );
QCOMPARE( mVertexTool->mDraggingVertex->vertexId, 1 );
mouseClick( 5, 7.5, Qt::LeftButton );
QCOMPARE( mLayerLineM->undoStack()->index(), 1 );
// when adding a vertex in the middle of an existing segment with m values, the m value should be linearly interpolated
QCOMPARE( mLayerLineM->getFeature( mFidLineMF2 ).geometry().asWkt( 1 ), QStringLiteral( "LineString M (5 7 5, 5 7.5 6, 7 7 10)" ) );
mLayerLineM->undoStack()->undo();
QCOMPARE( mLayerLineM->undoStack()->index(), 0 );
QCOMPARE( mLayerLineM->getFeature( mFidLineMF2 ).geometry().asWkt( 1 ), QStringLiteral( "LineString M (5 7 5, 7 7 10)" ) );
// inserting vertex via double-click
mouseDoubleClick( 5.2, 5.2, Qt::LeftButton );
QCOMPARE( mVertexTool->mDraggingVertexType, QgsVertexTool::DraggingVertexType::AddingVertex );
QCOMPARE( mVertexTool->mDraggingVertex->layer->id(), mLayerLineM->id() );
QCOMPARE( mVertexTool->mDraggingVertex->fid, mFidLineMF1 );
QCOMPARE( mVertexTool->mDraggingVertex->vertexId, 1 );
mouseClick( 5, 5.5, Qt::LeftButton );
QCOMPARE( mLayerLineM->undoStack()->index(), 1 );
QCOMPARE( mLayerLineM->getFeature( mFidLineMF1 ).geometry().asWkt( 1 ), QStringLiteral( "LineString M (5 5 1, 5 5.5 1, 6 6 1, 7 5 1)" ) );
mLayerLineM->undoStack()->undo();
QCOMPARE( mLayerLineM->undoStack()->index(), 0 );
QCOMPARE( mLayerLineM->getFeature( mFidLineMF1 ).geometry().asWkt( 1 ), QStringLiteral( "LineString M (5 5 1, 6 6 1, 7 5 1)" ) );
mouseDoubleClick( 5.3, 7, Qt::LeftButton );
QCOMPARE( mVertexTool->mDraggingVertexType, QgsVertexTool::DraggingVertexType::AddingVertex );
QCOMPARE( mVertexTool->mDraggingVertex->layer->id(), mLayerLineM->id() );
QCOMPARE( mVertexTool->mDraggingVertex->fid, mFidLineMF2 );
QCOMPARE( mVertexTool->mDraggingVertex->vertexId, 1 );
mouseClick( 5, 7.5, Qt::LeftButton );
QCOMPARE( mLayerLineM->undoStack()->index(), 1 );
QCOMPARE( mLayerLineM->getFeature( mFidLineMF2 ).geometry().asWkt( 1 ), QStringLiteral( "LineString M (5 7 5, 5 7.5 6, 7 7 10)" ) );
mLayerLineM->undoStack()->undo();
QCOMPARE( mLayerLineM->undoStack()->index(), 0 );
QCOMPARE( mLayerLineM->getFeature( mFidLineMF2 ).geometry().asWkt( 1 ), QStringLiteral( "LineString M (5 7 5, 7 7 10)" ) );
// insert vertex at endpoint
// offset of the endpoint marker - currently set as 15px away from the last vertex in direction of the line
const double offsetInMapUnits = 15 * mCanvas->mapSettings().mapUnitsPerPixel();
mouseMove( 5, 5 ); // first we need to move to the vertex
mouseClick( 5 - offsetInMapUnits / M_SQRT2, 5 - offsetInMapUnits / M_SQRT2, Qt::LeftButton );
QCOMPARE( mVertexTool->mDraggingVertexType, QgsVertexTool::DraggingVertexType::AddingEndpoint );
QCOMPARE( mVertexTool->mDraggingVertex->layer->id(), mLayerLineM->id() );
QCOMPARE( mVertexTool->mDraggingVertex->fid, mFidLineMF1 );
QCOMPARE( mVertexTool->mDraggingVertex->vertexId, 0 );
mouseClick( 5, 4, Qt::LeftButton );
QCOMPARE( mLayerLineM->undoStack()->index(), 1 );
QCOMPARE( mLayerLineM->getFeature( mFidLineMF1 ).geometry().asWkt( 1 ), QStringLiteral( "LineString M (5 4 222, 5 5 1, 6 6 1, 7 5 1)" ) );
mLayerLineM->undoStack()->undo();
QCOMPARE( mLayerLineM->undoStack()->index(), 0 );
QCOMPARE( mLayerLineM->getFeature( mFidLineMF1 ).geometry().asWkt( 1 ), QStringLiteral( "LineString M (5 5 1, 6 6 1, 7 5 1)" ) );
}
void TestQgsVertexTool::testAddVertexAtEndpoint() void TestQgsVertexTool::testAddVertexAtEndpoint()
{ {
// offset of the endpoint marker - currently set as 15px away from the last vertex in direction of the line // offset of the endpoint marker - currently set as 15px away from the last vertex in direction of the line

View File

@ -0,0 +1,26 @@
vcpkg_from_github(
OUT_SOURCE_PATH SOURCE_PATH
REPO libspatialindex/libspatialindex
REF "${VERSION}"
SHA512 a508a9ed4019641bdaaa53533505531f3db440b046a9c7d9f78ed480293200c51796c2d826a6bb9b4f9543d60bb0fef9e4c885ec3f09326cfa4d2fb81c1593aa
HEAD_REF master
)
vcpkg_cmake_configure(
SOURCE_PATH "${SOURCE_PATH}"
WINDOWS_USE_MSBUILD
OPTIONS
-DCMAKE_DEBUG_POSTFIX=d
-DSIDX_BUILD_TESTS:BOOL=OFF
)
vcpkg_cmake_install()
vcpkg_cmake_config_fixup(CONFIG_PATH lib/cmake/${PORT})
vcpkg_fixup_pkgconfig()
vcpkg_copy_pdbs()
#Debug
file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include")
# Handle copyright
file(INSTALL "${SOURCE_PATH}/COPYING" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright)

View File

@ -0,0 +1,18 @@
{
"name": "libspatialindex",
"version": "2.0.0",
"description": "C++ implementation of R*-tree, an MVR-tree and a TPR-tree with C API.",
"homepage": "http://libspatialindex.github.com",
"license": "MIT",
"dependencies": [
{
"name": "vcpkg-cmake",
"host": true
},
{
"name": "vcpkg-cmake-config",
"host": true
},
"zlib"
]
}