mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
Rewrite addTopologicalPoints() and remove legacy snapping code + unit test
This commit is contained in:
parent
cbf5e9c9c9
commit
24c5b0326f
@ -286,6 +286,7 @@ should now call QgsCoordinateReferenceSystem::invalidateCache() and QgsCoordinat
|
||||
- QgsSymbologyV2Conversion was removed. Reading of renderers from pre-1.0 versions is not supported anymore.
|
||||
- QgsTextAnnotationItem. Use QgsTextAnnotation instead.
|
||||
- QgsSnapper. Use QgsSnappingUtils instead.
|
||||
- QgsSnappingResult. Use QgsSnappingUtils instead.
|
||||
- QgsMapCanvasSnapper. Use QgsMapCanvas::snappingUtils() instead.
|
||||
|
||||
|
||||
@ -2095,6 +2096,9 @@ displayExpression instead. For the map tip use mapTipTemplate() instead.
|
||||
- readXml() does not resolve references to joined layers. Call resolveReferences() when joined layers are available.
|
||||
- snapWithContext(), snapToGeometry() - last argument has changed from QgsSnapper::SnappingType to QgsSnappingResult::SnappingType (no change in functionality).
|
||||
- snapPoint() has been removed - use QgsPointLocator class instead.
|
||||
- snapWithContext() has been removed - use QgsPointLocator class instead.
|
||||
- insertSegmentVerticesForSnap() has been removed - use addTopologicalPoints() directly.
|
||||
|
||||
|
||||
QgsVectorLayerEditBuffer {#qgis_api_break_3_0_QgsVectorLayerEditBuffer}
|
||||
------------------------
|
||||
@ -2110,6 +2114,7 @@ QgsVectorLayerEditUtils {#qgis_api_break_3_0_QgsVectorLayerEditUtils}
|
||||
-----------------------
|
||||
|
||||
- addTopologicalPoints() now accepts a geometry reference, not a pointer.
|
||||
- insertSegmentVerticesForSnap() has been removed.
|
||||
|
||||
|
||||
QgsVectorLayerImport {#qgis_api_break_3_0_QgsVectorLayerImport}
|
||||
|
@ -137,7 +137,6 @@
|
||||
%Include qgsscalecalculator.sip
|
||||
%Include qgsscaleutils.sip
|
||||
%Include qgssimplifymethod.sip
|
||||
%Include qgssnapper.sip
|
||||
%Include qgssnappingutils.sip
|
||||
%Include qgsspatialindex.sip
|
||||
%Include qgssqlstatement.sip
|
||||
|
@ -1,38 +0,0 @@
|
||||
/** \ingroup core
|
||||
* Represents the result of a snapping operation.
|
||||
* */
|
||||
struct QgsSnappingResult
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include <qgssnapper.h>
|
||||
%End
|
||||
|
||||
/** Snap to vertex, to segment or both*/
|
||||
enum SnappingType
|
||||
{
|
||||
SnapToVertex,
|
||||
SnapToSegment,
|
||||
//snap to vertex and also to segment if no vertex is within the search tolerance
|
||||
SnapToVertexAndSegment
|
||||
};
|
||||
|
||||
/** The coordinates of the snapping result*/
|
||||
QgsPoint snappedVertex;
|
||||
/** The vertex index of snappedVertex
|
||||
or -1 if no such vertex number (e.g. snap to segment)*/
|
||||
int snappedVertexNr;
|
||||
/** The layer coordinates of the vertex before snappedVertex*/
|
||||
QgsPoint beforeVertex;
|
||||
/** The index of the vertex before snappedVertex
|
||||
or -1 if no such vertex*/
|
||||
int beforeVertexNr;
|
||||
/** The layer coordinates of the vertex after snappedVertex*/
|
||||
QgsPoint afterVertex;
|
||||
/** The index of the vertex after snappedVertex
|
||||
or -1 if no such vertex*/
|
||||
int afterVertexNr;
|
||||
/** Index of the snapped geometry*/
|
||||
qint64 snappedAtGeometry;
|
||||
/** Layer where the snap occurred*/
|
||||
const QgsVectorLayer* layer;
|
||||
};
|
@ -1043,15 +1043,6 @@ TODO QGIS 3.0 returns an enum instead of a magic constant
|
||||
:rtype: int
|
||||
%End
|
||||
|
||||
int insertSegmentVerticesForSnap( const QList<QgsSnappingResult> &snapResults );
|
||||
%Docstring
|
||||
Inserts vertices to the snapped segments.
|
||||
This is useful for topological editing if snap to segment is enabled.
|
||||
\param snapResults results collected from the snapping operation
|
||||
:return: 0 in case of success
|
||||
:rtype: int
|
||||
%End
|
||||
|
||||
|
||||
|
||||
virtual bool isEditable() const;
|
||||
@ -1068,20 +1059,6 @@ Returns true if the provider has been modified since the last commit
|
||||
:rtype: bool
|
||||
%End
|
||||
|
||||
int snapWithContext( const QgsPoint &startPoint,
|
||||
double snappingTolerance,
|
||||
QMultiMap < double, QgsSnappingResult > &snappingResults /Out/,
|
||||
QgsSnappingResult::SnappingType snap_to );
|
||||
%Docstring
|
||||
Snaps to segment or vertex within given tolerance
|
||||
\param startPoint point to snap (in layer coordinates)
|
||||
\param snappingTolerance distance tolerance for snapping
|
||||
\param snappingResults snapping results. Key is the distance between startPoint and snapping target
|
||||
\param snap_to to segment / to vertex
|
||||
:return: 0 in case of success
|
||||
:rtype: int
|
||||
%End
|
||||
|
||||
virtual void reload();
|
||||
%Docstring
|
||||
Synchronises with changes in the datasource
|
||||
|
@ -149,16 +149,10 @@ class QgsVectorLayerEditUtils
|
||||
*/
|
||||
int addTopologicalPoints( const QgsPoint& p );
|
||||
|
||||
/** Inserts vertices to the snapped segments.
|
||||
* This is useful for topological editing if snap to segment is enabled.
|
||||
* @param snapResults results collected from the snapping operation
|
||||
* @return 0 in case of success
|
||||
*/
|
||||
int insertSegmentVerticesForSnap( const QList<QgsSnappingResult>& snapResults );
|
||||
|
||||
protected:
|
||||
|
||||
/** Little helper function that gives bounding box from a list of points.
|
||||
@return 0 in case of success */
|
||||
int boundingBoxFromPointList( const QList<QgsPoint>& list, double& xmin, double& ymin, double& xmax, double& ymax ) const;
|
||||
|
||||
};
|
||||
|
@ -769,7 +769,6 @@ SET(QGIS_CORE_HDRS
|
||||
qgsscalecalculator.h
|
||||
qgsscaleutils.h
|
||||
qgssimplifymethod.h
|
||||
qgssnapper.h
|
||||
qgssnappingutils.h
|
||||
qgsspatialindex.h
|
||||
qgssqlexpressioncompiler.h
|
||||
|
@ -1,65 +0,0 @@
|
||||
/***************************************************************************
|
||||
qgssnapper.h
|
||||
------------
|
||||
begin : June 7, 2007
|
||||
copyright : (C) 2007 by Marco Hugentobler
|
||||
email : marco dot hugentobler at karto dot baug dot ethz dot ch
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSSNAPPER_H
|
||||
#define QGSSNAPPER_H
|
||||
|
||||
#include "qgis_core.h"
|
||||
#include "qgspoint.h"
|
||||
|
||||
class QgsVectorLayer;
|
||||
|
||||
/** \ingroup core
|
||||
* Represents the result of a snapping operation.
|
||||
* */
|
||||
// ### QGIS 3: remove from API
|
||||
struct CORE_EXPORT QgsSnappingResult
|
||||
{
|
||||
//! Snap to vertex, to segment or both
|
||||
enum SnappingType
|
||||
{
|
||||
SnapToVertex,
|
||||
SnapToSegment,
|
||||
//snap to vertex and also to segment if no vertex is within the search tolerance
|
||||
SnapToVertexAndSegment
|
||||
};
|
||||
|
||||
//! The coordinates of the snapping result
|
||||
QgsPoint snappedVertex;
|
||||
|
||||
/** The vertex index of snappedVertex
|
||||
or -1 if no such vertex number (e.g. snap to segment)*/
|
||||
int snappedVertexNr;
|
||||
//! The layer coordinates of the vertex before snappedVertex
|
||||
QgsPoint beforeVertex;
|
||||
|
||||
/** The index of the vertex before snappedVertex
|
||||
or -1 if no such vertex*/
|
||||
int beforeVertexNr;
|
||||
//! The layer coordinates of the vertex after snappedVertex
|
||||
QgsPoint afterVertex;
|
||||
|
||||
/** The index of the vertex after snappedVertex
|
||||
or -1 if no such vertex*/
|
||||
int afterVertexNr;
|
||||
//! Index of the snapped geometry
|
||||
QgsFeatureId snappedAtGeometry;
|
||||
//! Layer where the snap occurred
|
||||
const QgsVectorLayer *layer = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
@ -2582,127 +2582,6 @@ bool QgsVectorLayer::addFeatures( QgsFeatureList features, bool makeSelected )
|
||||
}
|
||||
|
||||
|
||||
int QgsVectorLayer::snapWithContext( const QgsPoint &startPoint, double snappingTolerance,
|
||||
QMultiMap<double, QgsSnappingResult> &snappingResults,
|
||||
QgsSnappingResult::SnappingType snap_to )
|
||||
{
|
||||
if ( !hasGeometryType() )
|
||||
return 1;
|
||||
|
||||
if ( snappingTolerance <= 0 || !mDataProvider )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
QgsRectangle searchRect( startPoint.x() - snappingTolerance, startPoint.y() - snappingTolerance,
|
||||
startPoint.x() + snappingTolerance, startPoint.y() + snappingTolerance );
|
||||
double sqrSnappingTolerance = snappingTolerance * snappingTolerance;
|
||||
|
||||
int n = 0;
|
||||
QgsFeature f;
|
||||
|
||||
if ( mCache->cachedGeometriesRect().contains( searchRect ) )
|
||||
{
|
||||
QgsGeometryMap &cachedGeometries = mCache->cachedGeometries();
|
||||
for ( QgsGeometryMap::iterator it = cachedGeometries.begin(); it != cachedGeometries.end() ; ++it )
|
||||
{
|
||||
QgsGeometry g = it.value();
|
||||
if ( g.boundingBox().intersects( searchRect ) )
|
||||
{
|
||||
snapToGeometry( startPoint, it.key(), g, sqrSnappingTolerance, snappingResults, snap_to );
|
||||
++n;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// snapping outside cached area
|
||||
|
||||
QgsFeatureIterator fit = getFeatures( QgsFeatureRequest()
|
||||
.setFilterRect( searchRect )
|
||||
.setFlags( QgsFeatureRequest::ExactIntersect )
|
||||
.setSubsetOfAttributes( QgsAttributeList() ) );
|
||||
|
||||
while ( fit.nextFeature( f ) )
|
||||
{
|
||||
snapToGeometry( startPoint, f.id(), f.geometry(), sqrSnappingTolerance, snappingResults, snap_to );
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
return n == 0 ? 2 : 0;
|
||||
}
|
||||
|
||||
void QgsVectorLayer::snapToGeometry( const QgsPoint &startPoint,
|
||||
QgsFeatureId featureId,
|
||||
const QgsGeometry &geom,
|
||||
double sqrSnappingTolerance,
|
||||
QMultiMap<double, QgsSnappingResult> &snappingResults,
|
||||
QgsSnappingResult::SnappingType snap_to ) const
|
||||
{
|
||||
if ( geom.isNull() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int atVertex, beforeVertex, afterVertex;
|
||||
double sqrDistVertexSnap, sqrDistSegmentSnap;
|
||||
QgsPoint snappedPoint;
|
||||
QgsSnappingResult snappingResultVertex;
|
||||
QgsSnappingResult snappingResultSegment;
|
||||
|
||||
if ( snap_to == QgsSnappingResult::SnapToVertex || snap_to == QgsSnappingResult::SnapToVertexAndSegment )
|
||||
{
|
||||
snappedPoint = geom.closestVertex( startPoint, atVertex, beforeVertex, afterVertex, sqrDistVertexSnap );
|
||||
if ( sqrDistVertexSnap < sqrSnappingTolerance )
|
||||
{
|
||||
snappingResultVertex.snappedVertex = snappedPoint;
|
||||
snappingResultVertex.snappedVertexNr = atVertex;
|
||||
snappingResultVertex.beforeVertexNr = beforeVertex;
|
||||
if ( beforeVertex != -1 ) // make sure the vertex is valid
|
||||
{
|
||||
snappingResultVertex.beforeVertex = geom.vertexAt( beforeVertex );
|
||||
}
|
||||
snappingResultVertex.afterVertexNr = afterVertex;
|
||||
if ( afterVertex != -1 ) // make sure the vertex is valid
|
||||
{
|
||||
snappingResultVertex.afterVertex = geom.vertexAt( afterVertex );
|
||||
}
|
||||
snappingResultVertex.snappedAtGeometry = featureId;
|
||||
snappingResultVertex.layer = this;
|
||||
snappingResults.insert( sqrt( sqrDistVertexSnap ), snappingResultVertex );
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ( snap_to == QgsSnappingResult::SnapToSegment || snap_to == QgsSnappingResult::SnapToVertexAndSegment ) // snap to segment
|
||||
{
|
||||
if ( geometryType() != QgsWkbTypes::PointGeometry ) // cannot snap to segment for points/multipoints
|
||||
{
|
||||
sqrDistSegmentSnap = geom.closestSegmentWithContext( startPoint, snappedPoint, afterVertex, nullptr, crs().isGeographic() ? 1e-12 : 1e-8 );
|
||||
|
||||
if ( sqrDistSegmentSnap < sqrSnappingTolerance )
|
||||
{
|
||||
snappingResultSegment.snappedVertex = snappedPoint;
|
||||
snappingResultSegment.snappedVertexNr = -1;
|
||||
snappingResultSegment.beforeVertexNr = afterVertex - 1;
|
||||
snappingResultSegment.afterVertexNr = afterVertex;
|
||||
snappingResultSegment.snappedAtGeometry = featureId;
|
||||
snappingResultSegment.beforeVertex = geom.vertexAt( afterVertex - 1 );
|
||||
snappingResultSegment.afterVertex = geom.vertexAt( afterVertex );
|
||||
snappingResultSegment.layer = this;
|
||||
snappingResults.insert( sqrt( sqrDistSegmentSnap ), snappingResultSegment );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int QgsVectorLayer::insertSegmentVerticesForSnap( const QList<QgsSnappingResult> &snapResults )
|
||||
{
|
||||
QgsVectorLayerEditUtils utils( this );
|
||||
return utils.insertSegmentVerticesForSnap( snapResults );
|
||||
}
|
||||
|
||||
|
||||
void QgsVectorLayer::setCoordinateSystem()
|
||||
{
|
||||
QgsDebugMsg( "----- Computing Coordinate System" );
|
||||
|
@ -32,7 +32,6 @@
|
||||
#include "qgsfeature.h"
|
||||
#include "qgsfeaturerequest.h"
|
||||
#include "qgsfields.h"
|
||||
#include "qgssnapper.h"
|
||||
#include "qgsvectordataprovider.h"
|
||||
#include "qgsvectorsimplifymethod.h"
|
||||
#include "qgseditformconfig.h"
|
||||
@ -1029,13 +1028,6 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
|
||||
*/
|
||||
int addTopologicalPoints( const QgsPoint &p );
|
||||
|
||||
/** Inserts vertices to the snapped segments.
|
||||
* This is useful for topological editing if snap to segment is enabled.
|
||||
* \param snapResults results collected from the snapping operation
|
||||
* \returns 0 in case of success
|
||||
*/
|
||||
int insertSegmentVerticesForSnap( const QList<QgsSnappingResult> &snapResults );
|
||||
|
||||
/** Access to labeling configuration.
|
||||
* \since QGIS 2.12
|
||||
* \note not available in Python bindings
|
||||
@ -1056,18 +1048,6 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
|
||||
//! Returns true if the provider has been modified since the last commit
|
||||
virtual bool isModified() const;
|
||||
|
||||
/** Snaps to segment or vertex within given tolerance
|
||||
* \param startPoint point to snap (in layer coordinates)
|
||||
* \param snappingTolerance distance tolerance for snapping
|
||||
* \param snappingResults snapping results. Key is the distance between startPoint and snapping target
|
||||
* \param snap_to to segment / to vertex
|
||||
* \returns 0 in case of success
|
||||
*/
|
||||
int snapWithContext( const QgsPoint &startPoint,
|
||||
double snappingTolerance,
|
||||
QMultiMap < double, QgsSnappingResult > &snappingResults SIP_OUT,
|
||||
QgsSnappingResult::SnappingType snap_to );
|
||||
|
||||
//! Synchronises with changes in the datasource
|
||||
virtual void reload() override;
|
||||
|
||||
@ -1904,21 +1884,6 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
|
||||
//! Goes through all features and finds a free id (e.g. to give it temporarily to a not-committed feature)
|
||||
QgsFeatureId findFreeId();
|
||||
|
||||
/** Snaps to a geometry and adds the result to the multimap if it is within the snapping result
|
||||
* \param startPoint start point of the snap
|
||||
* \param featureId id of feature
|
||||
* \param geom geometry to snap
|
||||
* \param sqrSnappingTolerance squared search tolerance of the snap
|
||||
* \param snappingResults list to which the result is appended
|
||||
* \param snap_to snap to vertex or to segment
|
||||
*/
|
||||
void snapToGeometry( const QgsPoint &startPoint,
|
||||
QgsFeatureId featureId,
|
||||
const QgsGeometry &geom,
|
||||
double sqrSnappingTolerance,
|
||||
QMultiMap<double, QgsSnappingResult> &snappingResults,
|
||||
QgsSnappingResult::SnappingType snap_to ) const;
|
||||
|
||||
//! Add joined attributes to a feature
|
||||
//void addJoinedAttributes( QgsFeature& f, bool all = false );
|
||||
|
||||
|
@ -665,11 +665,7 @@ int QgsVectorLayerEditUtils::addTopologicalPoints( const QgsPoint &p )
|
||||
if ( !L->hasGeometryType() )
|
||||
return 1;
|
||||
|
||||
QMultiMap<double, QgsSnappingResult> snapResults; //results from the snapper object
|
||||
//we also need to snap to vertex to make sure the vertex does not already exist in this geometry
|
||||
QMultiMap<double, QgsSnappingResult> vertexSnapResults;
|
||||
|
||||
QList<QgsSnappingResult> filteredSnapResults; //we filter out the results that are on existing vertices
|
||||
double segmentSearchEpsilon = L->crs().isGeographic() ? 1e-12 : 1e-8;
|
||||
|
||||
//work with a tolerance because coordinate projection may introduce some rounding
|
||||
double threshold = 0.0000001;
|
||||
@ -682,68 +678,57 @@ int QgsVectorLayerEditUtils::addTopologicalPoints( const QgsPoint &p )
|
||||
threshold = 0.0001;
|
||||
}
|
||||
|
||||
QgsRectangle searchRect( p.x() - threshold, p.y() - threshold,
|
||||
p.x() + threshold, p.y() + threshold );
|
||||
double sqrSnappingTolerance = threshold * threshold;
|
||||
|
||||
if ( L->snapWithContext( p, threshold, snapResults, QgsSnappingResult::SnapToSegment ) != 0 )
|
||||
QgsFeature f;
|
||||
QgsFeatureIterator fit = L->getFeatures( QgsFeatureRequest()
|
||||
.setFilterRect( searchRect )
|
||||
.setFlags( QgsFeatureRequest::ExactIntersect )
|
||||
.setSubsetOfAttributes( QgsAttributeList() ) );
|
||||
|
||||
QMap<QgsFeatureId, QgsGeometry> features;
|
||||
QMap<QgsFeatureId, int> segments;
|
||||
|
||||
while ( fit.nextFeature( f ) )
|
||||
{
|
||||
int afterVertex;
|
||||
QgsPoint snappedPoint;
|
||||
double sqrDistSegmentSnap = f.geometry().closestSegmentWithContext( p, snappedPoint, afterVertex, nullptr, segmentSearchEpsilon );
|
||||
if ( sqrDistSegmentSnap < sqrSnappingTolerance )
|
||||
{
|
||||
segments[f.id()] = afterVertex;
|
||||
features[f.id()] = f.geometry();
|
||||
}
|
||||
}
|
||||
|
||||
if ( segments.isEmpty() )
|
||||
return 2;
|
||||
}
|
||||
|
||||
QMultiMap<double, QgsSnappingResult>::const_iterator snap_it = snapResults.constBegin();
|
||||
QMultiMap<double, QgsSnappingResult>::const_iterator vertex_snap_it;
|
||||
for ( ; snap_it != snapResults.constEnd(); ++snap_it )
|
||||
for ( QMap<QgsFeatureId, int>::const_iterator it = segments.constBegin(); it != segments.constEnd(); ++it )
|
||||
{
|
||||
//test if p is already a vertex of this geometry. If yes, don't insert it
|
||||
bool vertexAlreadyExists = false;
|
||||
if ( L->snapWithContext( p, threshold, vertexSnapResults, QgsSnappingResult::SnapToVertex ) != 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
QgsFeatureId fid = it.key();
|
||||
int segmentAfterVertex = it.value();
|
||||
QgsGeometry geom = features[fid];
|
||||
|
||||
vertex_snap_it = vertexSnapResults.constBegin();
|
||||
for ( ; vertex_snap_it != vertexSnapResults.constEnd(); ++vertex_snap_it )
|
||||
{
|
||||
if ( snap_it.value().snappedAtGeometry == vertex_snap_it.value().snappedAtGeometry )
|
||||
{
|
||||
vertexAlreadyExists = true;
|
||||
}
|
||||
}
|
||||
int atVertex, beforeVertex, afterVertex;
|
||||
double sqrDistVertexSnap;
|
||||
geom.closestVertex( p, atVertex, beforeVertex, afterVertex, sqrDistVertexSnap );
|
||||
|
||||
if ( !vertexAlreadyExists )
|
||||
if ( sqrDistVertexSnap < sqrSnappingTolerance )
|
||||
continue; // the vertex already exists - do not insert it
|
||||
|
||||
if ( !L->insertVertex( p.x(), p.y(), fid, segmentAfterVertex ) )
|
||||
{
|
||||
filteredSnapResults.push_back( *snap_it );
|
||||
QgsDebugMsg( "failed to insert topo point" );
|
||||
}
|
||||
}
|
||||
insertSegmentVerticesForSnap( filteredSnapResults );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int QgsVectorLayerEditUtils::insertSegmentVerticesForSnap( const QList<QgsSnappingResult> &snapResults )
|
||||
{
|
||||
if ( !L->hasGeometryType() )
|
||||
return 1;
|
||||
|
||||
int returnval = 0;
|
||||
QgsPoint layerPoint;
|
||||
|
||||
QList<QgsSnappingResult>::const_iterator it = snapResults.constBegin();
|
||||
for ( ; it != snapResults.constEnd(); ++it )
|
||||
{
|
||||
if ( it->snappedVertexNr == -1 ) // segment snap
|
||||
{
|
||||
layerPoint = it->snappedVertex;
|
||||
if ( !insertVertex( layerPoint.x(), layerPoint.y(), it->snappedAtGeometry, it->afterVertexNr ) )
|
||||
{
|
||||
returnval = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int QgsVectorLayerEditUtils::boundingBoxFromPointList( const QList<QgsPoint> &list, double &xmin, double &ymin, double &xmax, double &ymax ) const
|
||||
{
|
||||
if ( list.size() < 1 )
|
||||
|
@ -176,19 +176,14 @@ class CORE_EXPORT QgsVectorLayerEditUtils
|
||||
*/
|
||||
int addTopologicalPoints( const QgsPoint &p );
|
||||
|
||||
/** Inserts vertices to the snapped segments.
|
||||
* This is useful for topological editing if snap to segment is enabled.
|
||||
* \param snapResults results collected from the snapping operation
|
||||
* \returns 0 in case of success
|
||||
*/
|
||||
int insertSegmentVerticesForSnap( const QList<QgsSnappingResult> &snapResults );
|
||||
|
||||
protected:
|
||||
|
||||
/** Little helper function that gives bounding box from a list of points.
|
||||
\returns 0 in case of success */
|
||||
int boundingBoxFromPointList( const QList<QgsPoint> &list, double &xmin, double &ymin, double &xmax, double &ymax ) const;
|
||||
|
||||
private:
|
||||
|
||||
QgsVectorLayer *L = nullptr;
|
||||
};
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <QDesktopServices>
|
||||
|
||||
//qgis includes...
|
||||
#include <qgsgeometry.h>
|
||||
#include <qgsmaplayer.h>
|
||||
#include <qgsvectordataprovider.h>
|
||||
#include <qgsvectorlayer.h>
|
||||
@ -103,6 +104,7 @@ class TestQgsVectorLayer : public QObject
|
||||
void minimumValue();
|
||||
void maximumValue();
|
||||
void isSpatial();
|
||||
void testAddTopologicalPoints();
|
||||
};
|
||||
|
||||
void TestQgsVectorLayer::initTestCase()
|
||||
@ -337,5 +339,45 @@ void TestQgsVectorLayer::isSpatial()
|
||||
QVERIFY( !mpNonSpatialLayer->isSpatial() );
|
||||
}
|
||||
|
||||
void TestQgsVectorLayer::testAddTopologicalPoints()
|
||||
{
|
||||
// create a simple linestring layer
|
||||
|
||||
QgsVectorLayer *layerLine = new QgsVectorLayer( "LineString?crs=EPSG:27700", "layer line", "memory" );
|
||||
QVERIFY( layerLine->isValid() );
|
||||
|
||||
QgsPolyline line1;
|
||||
line1 << QgsPoint( 2, 1 ) << QgsPoint( 1, 1 ) << QgsPoint( 1, 3 );
|
||||
QgsFeature lineF1;
|
||||
lineF1.setGeometry( QgsGeometry::fromPolyline( line1 ) );
|
||||
|
||||
layerLine->startEditing();
|
||||
layerLine->addFeature( lineF1 );
|
||||
QgsFeatureId fidLineF1 = lineF1.id();
|
||||
QCOMPARE( layerLine->featureCount(), ( long )1 );
|
||||
|
||||
QCOMPARE( layerLine->undoStack()->index(), 1 );
|
||||
|
||||
// outside of the linestring - nothing should happen
|
||||
layerLine->addTopologicalPoints( QgsPoint( 2, 2 ) );
|
||||
|
||||
QCOMPARE( layerLine->undoStack()->index(), 1 );
|
||||
QCOMPARE( layerLine->getFeature( fidLineF1 ).geometry(), QgsGeometry::fromWkt( "LINESTRING(2 1, 1 1, 1 3)" ) );
|
||||
|
||||
// add point at an existing vertex
|
||||
layerLine->addTopologicalPoints( QgsPoint( 1, 1 ) );
|
||||
|
||||
QCOMPARE( layerLine->undoStack()->index(), 1 );
|
||||
QCOMPARE( layerLine->getFeature( fidLineF1 ).geometry(), QgsGeometry::fromWkt( "LINESTRING(2 1, 1 1, 1 3)" ) );
|
||||
|
||||
// add point on segment of linestring
|
||||
layerLine->addTopologicalPoints( QgsPoint( 1, 2 ) );
|
||||
|
||||
QCOMPARE( layerLine->undoStack()->index(), 2 );
|
||||
QCOMPARE( layerLine->getFeature( fidLineF1 ).geometry(), QgsGeometry::fromWkt( "LINESTRING(2 1, 1 1, 1 2, 1 3)" ) );
|
||||
|
||||
delete layerLine;
|
||||
}
|
||||
|
||||
QGSTEST_MAIN( TestQgsVectorLayer )
|
||||
#include "testqgsvectorlayer.moc"
|
||||
|
Loading…
x
Reference in New Issue
Block a user