[FEATURE][processing] Snap geometries algorithm allows snapping

to other layer types, supports point/line layers

Fix #14791, #15313
This commit is contained in:
Nyall Dawson 2016-11-05 19:38:49 +10:00
parent c3a978b9da
commit dae0a01761
9 changed files with 589 additions and 15 deletions

View File

@ -31,7 +31,6 @@ from qgis.core import QgsFeature
from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.core.parameters import ParameterVector, ParameterNumber
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
from processing.core.outputs import OutputVector
from processing.tools import dataobjects, vector
@ -57,10 +56,6 @@ class SnapGeometriesToLayer(GeoAlgorithm):
reference_layer = dataobjects.getObjectFromUri(self.getParameterValue(self.REFERENCE_LAYER))
tolerance = self.getParameterValue(self.TOLERANCE)
if not layer.geometryType() == reference_layer.geometryType():
raise GeoAlgorithmExecutionException(
self.tr('Input layer and reference layer must have the same geometry type (eg both are line layers)'))
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
layer.fields(), layer.wkbType(), layer.crs())

View File

@ -0,0 +1,16 @@
<GMLFeatureClassList>
<GMLFeatureClass>
<Name>snap_points_to_points</Name>
<ElementPath>snap_points_to_points</ElementPath>
<!--POINT-->
<GeometryType>1</GeometryType>
<SRSName>EPSG:4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>9</FeatureCount>
<ExtentXMin>0.20114</ExtentXMin>
<ExtentXMax>7.97127</ExtentXMax>
<ExtentYMin>-4.82759</ExtentYMin>
<ExtentYMax>2.74139</ExtentYMax>
</DatasetSpecificInfo>
</GMLFeatureClass>
</GMLFeatureClassList>

View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=""
xmlns:ogr="http://ogr.maptools.org/"
xmlns:gml="http://www.opengis.net/gml">
<gml:boundedBy>
<gml:Box>
<gml:coord><gml:X>0</gml:X><gml:Y>-5</gml:Y></gml:coord>
<gml:coord><gml:X>7.971265678449257</gml:X><gml:Y>3</gml:Y></gml:coord>
</gml:Box>
</gml:boundedBy>
<gml:featureMember>
<ogr:snap_points_to_points fid="points.0">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>1,1</gml:coordinates></gml:Point></ogr:geometryProperty>
</ogr:snap_points_to_points>
</gml:featureMember>
<gml:featureMember>
<ogr:snap_points_to_points fid="points.1">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>3,3</gml:coordinates></gml:Point></ogr:geometryProperty>
</ogr:snap_points_to_points>
</gml:featureMember>
<gml:featureMember>
<ogr:snap_points_to_points fid="points.2">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>2,2</gml:coordinates></gml:Point></ogr:geometryProperty>
</ogr:snap_points_to_points>
</gml:featureMember>
<gml:featureMember>
<ogr:snap_points_to_points fid="points.3">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>5,2</gml:coordinates></gml:Point></ogr:geometryProperty>
</ogr:snap_points_to_points>
</gml:featureMember>
<gml:featureMember>
<ogr:snap_points_to_points fid="points.4">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>4,1</gml:coordinates></gml:Point></ogr:geometryProperty>
</ogr:snap_points_to_points>
</gml:featureMember>
<gml:featureMember>
<ogr:snap_points_to_points fid="points.5">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>0,-5</gml:coordinates></gml:Point></ogr:geometryProperty>
</ogr:snap_points_to_points>
</gml:featureMember>
<gml:featureMember>
<ogr:snap_points_to_points fid="points.6">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>7.971265678449257,0.609122006841505</gml:coordinates></gml:Point></ogr:geometryProperty>
</ogr:snap_points_to_points>
</gml:featureMember>
<gml:featureMember>
<ogr:snap_points_to_points fid="points.7">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>7,-1</gml:coordinates></gml:Point></ogr:geometryProperty>
</ogr:snap_points_to_points>
</gml:featureMember>
<gml:featureMember>
<ogr:snap_points_to_points fid="points.8">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>0,-1</gml:coordinates></gml:Point></ogr:geometryProperty>
</ogr:snap_points_to_points>
</gml:featureMember>
</ogr:FeatureCollection>

View File

@ -1417,3 +1417,18 @@ tests:
OUTPUT:
name: expected/snap_polys_to_polys.gml
type: vector
- algorithm: qgis:snapgeometriestolayer
name: Snap points to points
params:
INPUT:
name: snap_points.gml
type: vector
REFERENCE_LAYER:
name: points.gml
type: vector
TOLERANCE: 1.0
results:
OUTPUT:
name: expected/snap_points_to_points.gml
type: vector

View File

@ -0,0 +1,16 @@
<GMLFeatureClassList>
<GMLFeatureClass>
<Name>snap_points</Name>
<ElementPath>snap_points</ElementPath>
<!--POINT-->
<GeometryType>1</GeometryType>
<SRSName>EPSG:4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>9</FeatureCount>
<ExtentXMin>0.20114</ExtentXMin>
<ExtentXMax>7.97127</ExtentXMax>
<ExtentYMin>-4.82759</ExtentYMin>
<ExtentYMax>2.74139</ExtentYMax>
</DatasetSpecificInfo>
</GMLFeatureClass>
</GMLFeatureClassList>

View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=""
xmlns:ogr="http://ogr.maptools.org/"
xmlns:gml="http://www.opengis.net/gml">
<gml:boundedBy>
<gml:Box>
<gml:coord><gml:X>0.2011402508551881</gml:X><gml:Y>-4.827594070695552</gml:Y></gml:coord>
<gml:coord><gml:X>7.971265678449257</gml:X><gml:Y>2.74139110604333</gml:Y></gml:coord>
</gml:Box>
</gml:boundedBy>
<gml:featureMember>
<ogr:snap_points fid="points.0">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>1,1</gml:coordinates></gml:Point></ogr:geometryProperty>
</ogr:snap_points>
</gml:featureMember>
<gml:featureMember>
<ogr:snap_points fid="points.1">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>3.134093500570125,2.74139110604333</gml:coordinates></gml:Point></ogr:geometryProperty>
</ogr:snap_points>
</gml:featureMember>
<gml:featureMember>
<ogr:snap_points fid="points.2">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>2,2</gml:coordinates></gml:Point></ogr:geometryProperty>
</ogr:snap_points>
</gml:featureMember>
<gml:featureMember>
<ogr:snap_points fid="points.3">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>5.25860889395667,1.578563283922463</gml:coordinates></gml:Point></ogr:geometryProperty>
</ogr:snap_points>
</gml:featureMember>
<gml:featureMember>
<ogr:snap_points fid="points.4">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>3.683922462941847,0.961687571265678</gml:coordinates></gml:Point></ogr:geometryProperty>
</ogr:snap_points>
</gml:featureMember>
<gml:featureMember>
<ogr:snap_points fid="points.5">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>0.201140250855188,-4.827594070695552</gml:coordinates></gml:Point></ogr:geometryProperty>
</ogr:snap_points>
</gml:featureMember>
<gml:featureMember>
<ogr:snap_points fid="points.6">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>7.971265678449257,0.609122006841505</gml:coordinates></gml:Point></ogr:geometryProperty>
</ogr:snap_points>
</gml:featureMember>
<gml:featureMember>
<ogr:snap_points fid="points.7">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>7.181984036488029,-1.268187001140251</gml:coordinates></gml:Point></ogr:geometryProperty>
</ogr:snap_points>
</gml:featureMember>
<gml:featureMember>
<ogr:snap_points fid="points.8">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>0.220296465222349,-1.210718358038768</gml:coordinates></gml:Point></ogr:geometryProperty>
</ogr:snap_points>
</gml:featureMember>
</ogr:FeatureCollection>

View File

@ -24,6 +24,8 @@
#include "qgsvectordataprovider.h"
#include "qgsgeometryutils.h"
#include "qgsmapsettings.h"
#include "qgssurface.h"
#include "qgscurve.h"
///@cond PRIVATE
@ -328,7 +330,17 @@ void QgsSnapIndex::addGeometry( const QgsAbstractGeometry* geom )
{
for ( int iRing = 0, nRings = geom->ringCount( iPart ); iRing < nRings; ++iRing )
{
for ( int iVert = 0, nVerts = geom->vertexCount( iPart, iRing ) - 1; iVert < nVerts; ++iVert )
int nVerts = geom->vertexCount( iPart, iRing );
if ( dynamic_cast< const QgsSurface* >( geom ) )
nVerts--;
else if ( const QgsCurve* curve = dynamic_cast< const QgsCurve* >( geom ) )
{
if ( curve->isClosed() )
nVerts--;
}
for ( int iVert = 0; iVert < nVerts; ++iVert )
{
CoordIdx* idx = new CoordIdx( geom, QgsVertexId( iPart, iRing, iVert ) );
CoordIdx* idx1 = new CoordIdx( geom, QgsVertexId( iPart, iRing, iVert + 1 ) );
@ -469,16 +481,15 @@ void QgsGeometrySnapper::processFeature( QgsFeature& feature )
QgsGeometry QgsGeometrySnapper::snapGeometry( const QgsGeometry& geometry ) const
{
// can't snap to different geometry types
if ( geometry.type() != mReferenceLayer->geometryType() )
return geometry;
QgsPointV2 center = QgsPointV2( geometry.geometry()->boundingBox().center() );
QgsPointV2 center = dynamic_cast< const QgsPointV2* >( geometry.geometry() ) ? *dynamic_cast< const QgsPointV2* >( geometry.geometry() ) :
QgsPointV2( geometry.geometry()->boundingBox().center() );
// Get potential reference features and construct snap index
QList<QgsGeometry> refGeometries;
mIndexMutex.lock();
QgsFeatureIds refFeatureIds = mIndex.intersects( geometry.boundingBox() ).toSet();
QgsRectangle searchBounds = geometry.boundingBox();
searchBounds.grow( mSnapTolerance );
QgsFeatureIds refFeatureIds = mIndex.intersects( searchBounds ).toSet();
mIndexMutex.unlock();
QgsFeatureRequest refFeatureRequest = QgsFeatureRequest().setFilterFids( refFeatureIds ).setSubsetOfAttributes( QgsAttributeList() );
@ -541,6 +552,10 @@ QgsGeometry QgsGeometrySnapper::snapGeometry( const QgsGeometry& geometry ) cons
}
}
//nothing more to do for points
if ( dynamic_cast< const QgsPointV2* >( subjGeom ) )
return QgsGeometry( subjGeom );
// SnapIndex for subject feature
QgsSnapIndex* subjSnapIndex = new QgsSnapIndex( center, 10 * mSnapTolerance );
subjSnapIndex->addGeometry( subjGeom );
@ -642,7 +657,14 @@ QgsGeometry QgsGeometrySnapper::snapGeometry( const QgsGeometry& geometry ) cons
int QgsGeometrySnapper::polyLineSize( const QgsAbstractGeometry* geom, int iPart, int iRing ) const
{
int nVerts = geom->vertexCount( iPart, iRing );
QgsPointV2 front = geom->vertexAt( QgsVertexId( iPart, iRing, 0 ) );
QgsPointV2 back = geom->vertexAt( QgsVertexId( iPart, iRing, nVerts - 1 ) );
return back == front ? nVerts - 1 : nVerts;
if ( dynamic_cast< const QgsSurface* >( geom ) )
{
QgsPointV2 front = geom->vertexAt( QgsVertexId( iPart, iRing, 0 ) );
QgsPointV2 back = geom->vertexAt( QgsVertexId( iPart, iRing, nVerts - 1 ) );
if ( front == back )
return nVerts - 1;
}
return nVerts;
}

View File

@ -77,6 +77,7 @@ ENDMACRO (ADD_QGIS_TEST)
# Tests:
ADD_QGIS_TEST(analyzertest testqgsvectoranalyzer.cpp)
ADD_QGIS_TEST(geometrysnappertest testqgsgeometrysnapper.cpp)
ADD_QGIS_TEST(openstreetmaptest testopenstreetmap.cpp)
ADD_QGIS_TEST(zonalstatisticstest testqgszonalstatistics.cpp)
ADD_QGIS_TEST(rastercalculatortest testqgsrastercalculator.cpp)

View File

@ -0,0 +1,391 @@
/***************************************************************************
testqgsgeometrysnapper.cpp
--------------------------
Date : November 2016
Copyright : (C) 2016 by Nyall Dawson
Email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <QtTest/QtTest>
//header for class being tested
#include "qgsgeometrysnapper.h"
#include "qgsgeometry.h"
#include <qgsapplication.h>
#include "qgsvectordataprovider.h"
#include "qgsvectorlayer.h"
class TestQgsGeometrySnapper : public QObject
{
Q_OBJECT
public:
private slots:
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase();// will be called after the last testfunction was executed.
void init() ;// will be called before each testfunction is executed.
void cleanup() ;// will be called after every testfunction.
//! Our tests proper begin here
void snapPolygonToPolygon();
void snapPolygonToLine();
void snapPolygonToPoint();
void snapLineToLine();
void snapLineToPolygon();
void snapLineToPoint();
void snapPointToPoint();
void snapPointToLine();
void snapPointToPolygon();
};
void TestQgsGeometrySnapper::initTestCase()
{
//
// Runs once before any tests are run
//
// init QGIS's paths - true means that all path will be inited from prefix
QgsApplication::init();
QgsApplication::initQgis();
}
void TestQgsGeometrySnapper::cleanupTestCase()
{
QgsApplication::exitQgis();
}
void TestQgsGeometrySnapper::init()
{
}
void TestQgsGeometrySnapper::cleanup()
{
}
void TestQgsGeometrySnapper::snapPolygonToPolygon()
{
QgsVectorLayer* rl = new QgsVectorLayer( QStringLiteral( "Polygon" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
QgsFeature ff( 0 );
QgsGeometry refGeom = QgsGeometry::fromWkt( QStringLiteral( "Polygon((0 0, 10 0, 10 10, 0 10, 0 0))" ) );
ff.setGeometry( refGeom );
QgsFeatureList flist;
flist << ff;
rl->dataProvider()->addFeatures( flist );
QgsGeometry polygonGeom = QgsGeometry::fromWkt( QStringLiteral( "Polygon((0.1 -0.1, 10.1 0, 9.9 10.1, 0 10, 0.1 -0.1))" ) );
QgsGeometrySnapper snapper( rl, 1 );
QgsGeometry result = snapper.snapGeometry( polygonGeom );
QCOMPARE( result.exportToWkt(), QStringLiteral( "Polygon ((0 0, 10 0, 10 10, 0 10, 0 0))" ) );
QgsGeometry polygonGeom2 = QgsGeometry::fromWkt( QStringLiteral( "Polygon((0.1 -0.1, 10.1 0, 0 10, 0.1 -0.1))" ) );
result = snapper.snapGeometry( polygonGeom2 );
QCOMPARE( result.exportToWkt(), QStringLiteral( "Polygon ((0 0, 10 0, 0 10, 0 0))" ) );
// insert new vertex
QgsGeometry polygonGeom3 = QgsGeometry::fromWkt( QStringLiteral( "Polygon((0.1 -0.1, 20.5 0.5, 20 10, 0 9.9, 0.1 -0.1))" ) );
result = snapper.snapGeometry( polygonGeom3 );
QCOMPARE( result.exportToWkt(), QStringLiteral( "Polygon ((0 0, 10 0, 20.5 0.5, 20 10, 10 10, 0 10, 0 0))" ) );
// remove vertex
QgsGeometry polygonGeom4 = QgsGeometry::fromWkt( QStringLiteral( "Polygon((0.1 -0.1, 10.1 0, 9.9 10.1, 5 10, 0 10, 0.1 -0.1))" ) );
result = snapper.snapGeometry( polygonGeom4 );
QCOMPARE( result.exportToWkt(), QStringLiteral( "Polygon ((0 0, 10 0, 10 10, 0 10, 0 0))" ) );
}
void TestQgsGeometrySnapper::snapLineToLine()
{
QgsVectorLayer* rl = new QgsVectorLayer( QStringLiteral( "Linestring" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
QgsFeature ff( 0 );
// closed linestrings
QgsGeometry refGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(0 0, 10 0, 10 10, 0 10, 0 0)" ) );
ff.setGeometry( refGeom );
QgsFeatureList flist;
flist << ff;
rl->dataProvider()->addFeatures( flist );
QgsGeometry lineGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 10.1 0, 9.9 10.1, 0 10, 0.1 -0.1)" ) );
QgsGeometrySnapper snapper( rl, 1 );
QgsGeometry result = snapper.snapGeometry( lineGeom );
QCOMPARE( result.exportToWkt(), QStringLiteral( "LineString (0 0, 10 0, 10 10, 0 10, 0 0)" ) );
QgsGeometry lineGeom2 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 10.1 0, 0 10, 0.1 -0.1)" ) );
result = snapper.snapGeometry( lineGeom2 );
QCOMPARE( result.exportToWkt(), QStringLiteral( "LineString (0 0, 10 0, 0 10, 0 0)" ) );
// insert new vertex
QgsGeometry lineGeom3 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 20.5 0.5, 20 10, 0 9.9, 0.1 -0.1)" ) );
result = snapper.snapGeometry( lineGeom3 );
QCOMPARE( result.exportToWkt(), QStringLiteral( "LineString (0 0, 10 0, 20.5 0.5, 20 10, 10 10, 0 10, 0 0)" ) );
// remove vertex
QgsGeometry lineGeom4 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 10.1 0, 9.9 10.1, 5 10, 0 10, 0.1 -0.1)" ) );
result = snapper.snapGeometry( lineGeom4 );
QCOMPARE( result.exportToWkt(), QStringLiteral( "LineString (0 0, 10 0, 10 10, 0 10, 0 0)" ) );
// unclosed linestrings
QgsGeometry lineGeom5 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 10.1 0, 9.9 10.1, 0 10)" ) );
result = snapper.snapGeometry( lineGeom5 );
QCOMPARE( result.exportToWkt(), QStringLiteral( "LineString (0 0, 10 0, 10 10, 0 10)" ) );
QgsGeometry lineGeom6 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 10.1 0, 0 10)" ) );
result = snapper.snapGeometry( lineGeom6 );
QCOMPARE( result.exportToWkt(), QStringLiteral( "LineString (0 0, 10 0, 0 10)" ) );
// insert new vertex
QgsGeometry lineGeom7 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 20.5 0.5, 20 10, 0 9.9)" ) );
result = snapper.snapGeometry( lineGeom7 );
QCOMPARE( result.exportToWkt(), QStringLiteral( "LineString (0 0, 10 0, 20.5 0.5, 20 10, 10 10, 0 10)" ) );
// remove vertex
QgsGeometry lineGeom8 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 10.1 0, 9.9 10.1, 5 10, 0 10)" ) );
result = snapper.snapGeometry( lineGeom8 );
QCOMPARE( result.exportToWkt(), QStringLiteral( "LineString (0 0, 10 0, 10 10, 0 10)" ) );
}
void TestQgsGeometrySnapper::snapLineToPolygon()
{
QgsVectorLayer* rl = new QgsVectorLayer( QStringLiteral( "Polygon" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
QgsFeature ff( 0 );
// closed linestrings
QgsGeometry refGeom = QgsGeometry::fromWkt( QStringLiteral( "Polygon((0 0, 10 0, 10 10, 0 10, 0 0))" ) );
ff.setGeometry( refGeom );
QgsFeatureList flist;
flist << ff;
rl->dataProvider()->addFeatures( flist );
QgsGeometry lineGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 10.1 0, 9.9 10.1, 0 10, 0.1 -0.1)" ) );
QgsGeometrySnapper snapper( rl, 1 );
QgsGeometry result = snapper.snapGeometry( lineGeom );
QCOMPARE( result.exportToWkt(), QStringLiteral( "LineString (0 0, 10 0, 10 10, 0 10, 0 0)" ) );
QgsGeometry lineGeom2 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 10.1 0, 0 10, 0.1 -0.1)" ) );
result = snapper.snapGeometry( lineGeom2 );
QCOMPARE( result.exportToWkt(), QStringLiteral( "LineString (0 0, 10 0, 0 10, 0 0)" ) );
// insert new vertex
QgsGeometry lineGeom3 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 20.5 0.5, 20 10, 0 9.9, 0.1 -0.1)" ) );
result = snapper.snapGeometry( lineGeom3 );
QCOMPARE( result.exportToWkt(), QStringLiteral( "LineString (0 0, 10 0, 20.5 0.5, 20 10, 10 10, 0 10, 0 0)" ) );
// remove vertex
QgsGeometry lineGeom4 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 10.1 0, 9.9 10.1, 5 10, 0 10, 0.1 -0.1)" ) );
result = snapper.snapGeometry( lineGeom4 );
QCOMPARE( result.exportToWkt(), QStringLiteral( "LineString (0 0, 10 0, 10 10, 0 10, 0 0)" ) );
// unclosed linestrings
QgsGeometry lineGeom5 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 10.1 0, 9.9 10.1, 0 10)" ) );
result = snapper.snapGeometry( lineGeom5 );
QCOMPARE( result.exportToWkt(), QStringLiteral( "LineString (0 0, 10 0, 10 10, 0 10)" ) );
QgsGeometry lineGeom6 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 10.1 0, 0 10)" ) );
result = snapper.snapGeometry( lineGeom6 );
QCOMPARE( result.exportToWkt(), QStringLiteral( "LineString (0 0, 10 0, 0 10)" ) );
// insert new vertex
QgsGeometry lineGeom7 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 20.5 0.5, 20 10, 0 9.9)" ) );
result = snapper.snapGeometry( lineGeom7 );
QCOMPARE( result.exportToWkt(), QStringLiteral( "LineString (0 0, 10 0, 20.5 0.5, 20 10, 10 10, 0 10)" ) );
// remove vertex
QgsGeometry lineGeom8 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 10.1 0, 9.9 10.1, 5 10, 0 10)" ) );
result = snapper.snapGeometry( lineGeom8 );
QCOMPARE( result.exportToWkt(), QStringLiteral( "LineString (0 0, 10 0, 10 10, 0 10)" ) );
}
void TestQgsGeometrySnapper::snapLineToPoint()
{
QgsVectorLayer* rl = new QgsVectorLayer( QStringLiteral( "Point" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
QgsGeometry refGeom = QgsGeometry::fromWkt( QStringLiteral( "Point(0 0)" ) );
QgsFeature ff( 0 );
ff.setGeometry( refGeom );
QgsGeometry refGeom2 = QgsGeometry::fromWkt( QStringLiteral( "Point(10 0)" ) );
QgsFeature ff2( 2 );
ff2.setGeometry( refGeom2 );
QgsFeatureList flist;
flist << ff << ff2;
rl->dataProvider()->addFeatures( flist );
QgsGeometry lineGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 10.1 0, 10 10, 0 10)" ) );
QgsGeometrySnapper snapper( rl, 1 );
QgsGeometry result = snapper.snapGeometry( lineGeom );
QCOMPARE( result.exportToWkt(), QStringLiteral( "LineString (0 0, 10 0, 10 10, 0 10)" ) );
QgsGeometry lineGeom2 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 10.1 0, 0 10)" ) );
result = snapper.snapGeometry( lineGeom2 );
QCOMPARE( result.exportToWkt(), QStringLiteral( "LineString (0 0, 10 0, 0 10)" ) );
// insert new vertex
QgsGeometry lineGeom3 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 20.0 0.0, 20 10, 0 10)" ) );
result = snapper.snapGeometry( lineGeom3 );
QCOMPARE( result.exportToWkt(), QStringLiteral( "LineString (0 0, 10 0, 20 0, 20 10, 0 10)" ) );
}
void TestQgsGeometrySnapper::snapPolygonToLine()
{
QgsVectorLayer* rl = new QgsVectorLayer( QStringLiteral( "Linestring" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
// closed linestring
QgsGeometry refGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(0 0, 10 0, 10 10, 0 10, 0 0)" ) );
QgsFeature ff( 0 );
ff.setGeometry( refGeom );
// unclosed linestring
QgsGeometry refGeom2 = QgsGeometry::fromWkt( QStringLiteral( "LineString(100 0, 110 0, 110 10, 100 10)" ) );
QgsFeature ff2( 2 );
ff2.setGeometry( refGeom2 );
QgsFeatureList flist;
flist << ff << ff2;
rl->dataProvider()->addFeatures( flist );
// snapping to closed linestring
QgsGeometry polygonGeom = QgsGeometry::fromWkt( QStringLiteral( "Polygon((0.1 -0.1, 10.1 0, 9.9 10.1, 0 10, 0.1 -0.1))" ) );
QgsGeometrySnapper snapper( rl, 1 );
QgsGeometry result = snapper.snapGeometry( polygonGeom );
QCOMPARE( result.exportToWkt(), QStringLiteral( "Polygon ((0 0, 10 0, 10 10, 0 10, 0 0))" ) );
QgsGeometry polygonGeom2 = QgsGeometry::fromWkt( QStringLiteral( "Polygon((0.1 -0.1, 10.1 0, 0 10, 0.1 -0.1))" ) );
result = snapper.snapGeometry( polygonGeom2 );
QCOMPARE( result.exportToWkt(), QStringLiteral( "Polygon ((0 0, 10 0, 0 10, 0 0))" ) );
// insert new vertex
QgsGeometry polygonGeom3 = QgsGeometry::fromWkt( QStringLiteral( "Polygon((0.1 -0.1, 20.5 0.5, 20 10, 0 9.9, 0.1 -0.1))" ) );
result = snapper.snapGeometry( polygonGeom3 );
QCOMPARE( result.exportToWkt(), QStringLiteral( "Polygon ((0 0, 10 0, 20.5 0.5, 20 10, 10 10, 0 10, 0 0))" ) );
// remove vertex
QgsGeometry polygonGeom4 = QgsGeometry::fromWkt( QStringLiteral( "Polygon((0.1 -0.1, 10.1 0, 9.9 10.1, 5 10, 0 10, 0.1 -0.1))" ) );
result = snapper.snapGeometry( polygonGeom4 );
QCOMPARE( result.exportToWkt(), QStringLiteral( "Polygon ((0 0, 10 0, 10 10, 0 10, 0 0))" ) );
// snapping to unclosed linestring
QgsGeometry polygonGeom5 = QgsGeometry::fromWkt( QStringLiteral( "Polygon((100.1 -0.1, 110.1 0, 109.9 10.1, 100 10, 100.1 -0.1))" ) );
result = snapper.snapGeometry( polygonGeom5 );
QCOMPARE( result.exportToWkt(), QStringLiteral( "Polygon ((100 0, 110 0, 110 10, 100 10, 100 0))" ) );
QgsGeometry polygonGeom6 = QgsGeometry::fromWkt( QStringLiteral( "Polygon((100.1 -0.1, 110.1 0, 100 10, 100.1 -0.1))" ) );
result = snapper.snapGeometry( polygonGeom6 );
QCOMPARE( result.exportToWkt(), QStringLiteral( "Polygon ((100 0, 110 0, 100 10, 100 0))" ) );
// insert new vertex
QgsGeometry polygonGeom7 = QgsGeometry::fromWkt( QStringLiteral( "Polygon((100.1 -0.1, 120.5 0.5, 120 10, 100 9.9, 100.1 -0.1))" ) );
result = snapper.snapGeometry( polygonGeom7 );
QCOMPARE( result.exportToWkt(), QStringLiteral( "Polygon ((100 0, 110 0, 120.5 0.5, 120 10, 110 10, 100 10, 100 0))" ) );
// remove vertex
QgsGeometry polygonGeom8 = QgsGeometry::fromWkt( QStringLiteral( "Polygon((100.1 -0.1, 110.1 0, 109.9 10.1, 105 10, 100 10, 100.1 -0.1))" ) );
result = snapper.snapGeometry( polygonGeom8 );
QCOMPARE( result.exportToWkt(), QStringLiteral( "Polygon ((100 0, 110 0, 110 10, 100 10, 100 0))" ) );
}
void TestQgsGeometrySnapper::snapPolygonToPoint()
{
QgsVectorLayer* rl = new QgsVectorLayer( QStringLiteral( "Point" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
QgsGeometry refGeom = QgsGeometry::fromWkt( QStringLiteral( "Point(0 0)" ) );
QgsFeature ff( 0 );
ff.setGeometry( refGeom );
QgsGeometry refGeom2 = QgsGeometry::fromWkt( QStringLiteral( "Point(10 0)" ) );
QgsFeature ff2( 2 );
ff2.setGeometry( refGeom2 );
QgsFeatureList flist;
flist << ff << ff2;
rl->dataProvider()->addFeatures( flist );
QgsGeometry polygonGeom = QgsGeometry::fromWkt( QStringLiteral( "Polygon((0.1 -0.1, 10.1 0, 10 10, 0 10, 0.1 -0.1))" ) );
QgsGeometrySnapper snapper( rl, 1 );
QgsGeometry result = snapper.snapGeometry( polygonGeom );
QCOMPARE( result.exportToWkt(), QStringLiteral( "Polygon ((0 0, 10 0, 10 10, 0 10, 0 0))" ) );
QgsGeometry polygonGeom2 = QgsGeometry::fromWkt( QStringLiteral( "Polygon((0.1 -0.1, 10.1 0, 0 10, 0.1 -0.1))" ) );
result = snapper.snapGeometry( polygonGeom2 );
QCOMPARE( result.exportToWkt(), QStringLiteral( "Polygon ((0 0, 10 0, 0 10, 0 0))" ) );
// insert new vertex
QgsGeometry polygonGeom3 = QgsGeometry::fromWkt( QStringLiteral( "Polygon((0.1 -0.1, 20.0 0.0, 20 10, 0 10, 0.1 -0.1))" ) );
result = snapper.snapGeometry( polygonGeom3 );
QCOMPARE( result.exportToWkt(), QStringLiteral( "Polygon ((0 0, 10 0, 20 0, 20 10, 0 10, 0 0))" ) );
}
void TestQgsGeometrySnapper::snapPointToPoint()
{
QgsVectorLayer* rl = new QgsVectorLayer( QStringLiteral( "Point" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
QgsGeometry refGeom = QgsGeometry::fromWkt( QStringLiteral( "Point(0 0)" ) );
QgsFeature ff( 0 );
ff.setGeometry( refGeom );
QgsGeometry refGeom2 = QgsGeometry::fromWkt( QStringLiteral( "Point(1 0)" ) );
QgsFeature ff2( 2 );
ff2.setGeometry( refGeom2 );
QgsFeatureList flist;
flist << ff << ff2;
rl->dataProvider()->addFeatures( flist );
QgsGeometry pointGeom = QgsGeometry::fromWkt( QStringLiteral( "Point(0.1 -0.1)" ) );
QgsGeometrySnapper snapper( rl, 1 );
QgsGeometry result = snapper.snapGeometry( pointGeom );
QCOMPARE( result.exportToWkt(), QStringLiteral( "Point (0 0)" ) );
pointGeom = QgsGeometry::fromWkt( QStringLiteral( "Point(0.6 -0.1)" ) );
result = snapper.snapGeometry( pointGeom );
QCOMPARE( result.exportToWkt(), QStringLiteral( "Point (1 0)" ) );
}
void TestQgsGeometrySnapper::snapPointToLine()
{
QgsVectorLayer* rl = new QgsVectorLayer( QStringLiteral( "Linestring" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
// closed linestring
QgsGeometry refGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(0 0, 10 0, 10 10, 0 10, 0 0)" ) );
QgsFeature ff( 0 );
ff.setGeometry( refGeom );
QgsFeatureList flist;
flist << ff;
rl->dataProvider()->addFeatures( flist );
QgsGeometry pointGeom = QgsGeometry::fromWkt( QStringLiteral( "Point(0.1 -0.1)" ) );
QgsGeometrySnapper snapper( rl, 1 );
QgsGeometry result = snapper.snapGeometry( pointGeom );
QCOMPARE( result.exportToWkt(), QStringLiteral( "Point (0 0)" ) );
pointGeom = QgsGeometry::fromWkt( QStringLiteral( "Point(10.6 -0.1)" ) );
result = snapper.snapGeometry( pointGeom );
QCOMPARE( result.exportToWkt(), QStringLiteral( "Point (10 0)" ) );
}
void TestQgsGeometrySnapper::snapPointToPolygon()
{
QgsVectorLayer* rl = new QgsVectorLayer( QStringLiteral( "Polygon" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
// closed linestring
QgsGeometry refGeom = QgsGeometry::fromWkt( QStringLiteral( "Polygon((0 0, 10 0, 10 10, 0 10, 0 0))" ) );
QgsFeature ff( 0 );
ff.setGeometry( refGeom );
QgsFeatureList flist;
flist << ff;
rl->dataProvider()->addFeatures( flist );
QgsGeometry pointGeom = QgsGeometry::fromWkt( QStringLiteral( "Point(0.1 -0.1)" ) );
QgsGeometrySnapper snapper( rl, 1 );
QgsGeometry result = snapper.snapGeometry( pointGeom );
QCOMPARE( result.exportToWkt(), QStringLiteral( "Point (0 0)" ) );
pointGeom = QgsGeometry::fromWkt( QStringLiteral( "Point(10.6 -0.1)" ) );
result = snapper.snapGeometry( pointGeom );
QCOMPARE( result.exportToWkt(), QStringLiteral( "Point (10 0)" ) );
}
QTEST_MAIN( TestQgsGeometrySnapper )
#include "testqgsgeometrysnapper.moc"