Skip to content

Commit

Permalink
[FEATURE] New snapping API with improved indexing (QEP 13)
Browse files Browse the repository at this point in the history
Merge branch 'snapping-improved'
  • Loading branch information
wonder-sk committed Jan 20, 2015
2 parents b029198 + 8177bbe commit cae4eb3
Show file tree
Hide file tree
Showing 52 changed files with 2,796 additions and 485 deletions.
2 changes: 2 additions & 0 deletions python/core/core.sip
Expand Up @@ -78,6 +78,7 @@
%Include qgspluginlayer.sip
%Include qgspluginlayerregistry.sip
%Include qgspoint.sip
%Include qgspointlocator.sip
%Include qgsproject.sip
%Include qgsprojectproperty.sip
%Include qgsprojectversion.sip
Expand All @@ -96,6 +97,7 @@
%Include qgsscaleutils.sip
%Include qgssimplifymethod.sip
%Include qgssnapper.sip
%Include qgssnappingutils.sip
%Include qgsspatialindex.sip
%Include qgstolerance.sip
%Include qgsvectordataprovider.sip
Expand Down
87 changes: 87 additions & 0 deletions python/core/qgspointlocator.sip
@@ -0,0 +1,87 @@

class QgsPointLocator : QObject
{
%TypeHeaderCode
#include <qgspointlocator.h>
%End

public:
/** Construct point locator for a layer.
* @arg destCRS if not null, will do the searches on data reprojected to the given CRS
* @arg extent if not null, will index only a subset of the layer
*/
explicit QgsPointLocator( QgsVectorLayer* layer, const QgsCoordinateReferenceSystem* destCRS = 0, const QgsRectangle* extent = 0 );

~QgsPointLocator();

enum Type { Invalid, Vertex, Edge, Area, All };

/** Prepare the index for queries. Does nothing if the index already exists */
void init();

struct Match
{
//! consruct invalid match
Match();

Match( QgsPointLocator::Type t, QgsVectorLayer* vl, QgsFeatureId fid, double dist, const QgsPoint& pt, int vertexIndex = 0 );

QgsPointLocator::Type type() const;

bool isValid() const;
bool hasVertex() const;
bool hasEdge() const;
bool hasArea() const;

//! for vertex / edge match
//! units depending on what class returns it (geom.cache: layer units, map canvas snapper: dest crs units)
double distance() const;

//! for vertex / edge match
//! coords depending on what class returns it (geom.cache: layer coords, map canvas snapper: dest coords)
QgsPoint point() const;

//! for vertex / edge match (first vertex of the edge)
int vertexIndex() const;

//! reference vector layer
QgsVectorLayer* layer() const;

QgsFeatureId featureId() const;

//! Only for a valid edge match - obtain endpoints of the edge
void edgePoints( QgsPoint& pt1 /Out/, QgsPoint& pt2 /Out/ ) const;
};

typedef QList<QgsPointLocator::Match> MatchList;

//! Interface that allows rejection of some matches in intersection queries
//! (e.g. a match can only belong to a particular feature / match must not be a particular point).
//! Implement the interface and pass its instance to QgsPointLocator or QgsSnappingUtils methods.
struct MatchFilter
{
virtual bool acceptMatch( const QgsPointLocator::Match& match ) = 0;
};

// intersection queries

//! Find nearest vertex to the specified point - up to distance specified by tolerance
//! Optional filter may discard unwanted matches.
Match nearestVertex( const QgsPoint& point, double tolerance, QgsPointLocator::MatchFilter* filter = 0 );
//! Find nearest edges to the specified point - up to distance specified by tolerance
//! Optional filter may discard unwanted matches.
Match nearestEdge( const QgsPoint& point, double tolerance, QgsPointLocator::MatchFilter* filter = 0 );
//! Find edges within a specified recangle
//! Optional filter may discard unwanted matches.
MatchList edgesInRect( const QgsRectangle& rect, QgsPointLocator::MatchFilter* filter = 0 );
//! Override of edgesInRect that construct rectangle from a center point and tolerance
MatchList edgesInRect( const QgsPoint& point, double tolerance, QgsPointLocator::MatchFilter* filter = 0 );

// point-in-polygon query

// TODO: function to return just the first match?
//! find out if the point is in any polygons
MatchList pointInPolygon( const QgsPoint& point );


};
90 changes: 90 additions & 0 deletions python/core/qgssnappingutils.sip
@@ -0,0 +1,90 @@

class QgsSnappingUtils : QObject
{
%TypeHeaderCode
#include <qgssnappingutils.h>
%End

public:
QgsSnappingUtils( QObject* parent /TransferThis/ = 0 );
~QgsSnappingUtils();

// main actions

/** get a point locator for the given layer. If such locator does not exist, it will be created */
QgsPointLocator* locatorForLayer( QgsVectorLayer* vl );

/** snap to map according to the current configuration (mode). Optional filter allows to discard unwanted matches. */
QgsPointLocator::Match snapToMap( const QPoint& point, QgsPointLocator::MatchFilter* filter = 0 );
QgsPointLocator::Match snapToMap( const QgsPoint& pointMap, QgsPointLocator::MatchFilter* filter = 0 );

/** snap to current layer */
QgsPointLocator::Match snapToCurrentLayer( const QPoint& point, int type, QgsPointLocator::MatchFilter* filter = 0 );

// environment setup

/** assign current map settings to the utils - used for conversion between screen coords to map coords */
void setMapSettings( const QgsMapSettings& settings );
const QgsMapSettings& mapSettings() const;

/** set current layer so that if mode is SnapCurrentLayer we know which layer to use */
void setCurrentLayer( QgsVectorLayer* layer );
QgsVectorLayer* currentLayer() const;


// configuration

//! modes for "snap to background"
enum SnapToMapMode
{
SnapCurrentLayer, //!< snap just to current layer (tolerance+type from QSettings)
SnapPerLayerConfig, //!< snap according to the configuration set in setLayers()
};

/** Set how the snapping to map is done */
void setSnapToMapMode( SnapToMapMode mode );
/** Find out how the snapping to map is done */
SnapToMapMode snapToMapMode() const;

enum IndexingStrategy
{
IndexAlwaysFull, //!< For all layers build index of full extent. Uses more memory, but queries are faster.
IndexNeverFull, //!< For all layers only create temporary indexes of small extent. Low memory usage, slower queries.
IndexHybrid //!< For "big" layers using IndexNeverFull, for the rest IndexAlwaysFull. Compromise between speed and memory usage.
};

/** Set a strategy for indexing geometry data - determines how fast and memory consuming the data structures will be */
void setIndexingStrategy( IndexingStrategy strategy );
/** Find out which strategy is used for indexing - by default hybrid indexing is used */
IndexingStrategy indexingStrategy() const;

/** configure options used when the mode is snap to current layer */
void setDefaultSettings( int type, double tolerance, QgsTolerance::UnitType unit );
/** query options used when the mode is snap to current layer */
void defaultSettings( int& type /Out/, double& tolerance /Out/, QgsTolerance::UnitType& unit /Out/ );

struct LayerConfig
{
LayerConfig( QgsVectorLayer* l, int t, double tol, QgsTolerance::UnitType u );

QgsVectorLayer* layer;
int type;
double tolerance;
QgsTolerance::UnitType unit;
};

/** Set layers which will be used for snapping */
void setLayers( const QList<QgsSnappingUtils::LayerConfig>& layers );
/** Query layers used for snapping */
QList<QgsSnappingUtils::LayerConfig> layers() const;

/** Set whether to consider intersections of nearby segments for snapping */
void setSnapOnIntersections( bool enabled );
/** Query whether to consider intersections of nearby segments for snapping */
bool snapOnIntersections() const;

public slots:
/** Read snapping configuration from the project */
void readConfigFromProject();

};
34 changes: 26 additions & 8 deletions python/core/qgstolerance.sip
Expand Up @@ -15,53 +15,71 @@ class QgsTolerance
Pixels
};

/**
* Static function to get vertex tolerance value.
* The value is read from settings and transformed if necessary.
* @return value of vertex tolerance in map units (not layer units)
* @note added in 2.8
*/
static double vertexSearchRadius( const QgsMapSettings& mapSettings );

/**
* Static function to get vertex tolerance value for a layer.
* The value is read from settings and transformed if necessary.
* @return value of vertex tolerance in map units
* @return value of vertex tolerance in layer units
*/
static double vertexSearchRadius( QgsMapLayer* layer, const QgsMapSettings& mapSettings );

/**
* Static function to get vertex tolerance value for a layer.
* The value is read from settings and transformed if necessary.
* @return value of vertex tolerance in map units
* @return value of vertex tolerance in layer units
*/
//! @deprecated since 2.4 - use override with QgsMapSettings
static double vertexSearchRadius( QgsMapLayer* layer, QgsMapRenderer* renderer ) /Deprecated/;

/**
* Static function to get default tolerance value for a layer.
* The value is read from settings and transformed if necessary.
* @return value of default tolerance in map units
* @return value of vertex tolerance in layer units
*/
static double defaultTolerance( QgsMapLayer* layer, const QgsMapSettings& mapSettings );

/**
* Static function to get default tolerance value for a layer.
* The value is read from settings and transformed if necessary.
* @return value of default tolerance in map units
* @return value of vertex tolerance in layer units
*/
//! @deprecated since 2.4 - use override with QgsMapSettings
static double defaultTolerance( QgsMapLayer* layer, QgsMapRenderer* renderer ) /Deprecated/;

/**
* Static function to translate tolerance value into current map unit value
* Static function to translate tolerance value into map units
* @param tolerance tolerance value to be translated
* @param layer reference layer
* @param mapSettings settings of the map
* @param units type of units to be translated
* @return value of tolerance in map units
* @note added in 2.8
*/
static double toleranceInMapUnits( double tolerance, const QgsMapSettings& mapSettings, QgsTolerance::UnitType units );

/**
* Static function to translate tolerance value into layer units
* @param tolerance tolerance value to be translated
* @param layer reference layer
* @param mapSettings settings of the map
* @param units type of units to be translated
* @return value of tolerance in layer units
*/
static double toleranceInMapUnits( double tolerance, QgsMapLayer* layer, const QgsMapSettings& mapSettings, UnitType units = MapUnits );

/**
* Static function to translate tolerance value into current map unit value
* Static function to translate tolerance value into layer units
* @param tolerance tolerance value to be translated
* @param layer reference layer
* @param renderer renderer
* @param units type of units to be translated
* @return value of tolerance in map units
* @return value of tolerance in layer units
*/
//! @deprecated since 2.4 - use the override with QgsMapSettings
static double toleranceInMapUnits( double tolerance, QgsMapLayer* layer, QgsMapRenderer* renderer, UnitType units = MapUnits ) /Deprecated/;
Expand Down
21 changes: 21 additions & 0 deletions python/gui/qgsmapcanvas.sip
Expand Up @@ -309,6 +309,23 @@ class QgsMapCanvas : QGraphicsView
* @note added in 2.3 */
QgsPreviewEffect::PreviewMode previewMode() const;

/** Return snapping utility class that is associated with map canvas.
* If no snapping utils instance has been associated previously, an internal will be created for convenience
* (so map tools do not need to test for existence of the instance).
*
* Main canvas in QGIS returns an instance which is always up-to-date with the project's snapping configuration.
* @note added in 2.8
*/
QgsSnappingUtils* snappingUtils() const;
/** Assign an instance of snapping utils to the map canvas.
* The instance is not owned by the canvas, so it is possible to use one instance in multiple canvases.
*
* For main canvas in QGIS, do not associate a different instance from the existing one (it is updated from
* the project's snapping configuration).
* @note added in 2.8
*/
void setSnappingUtils( QgsSnappingUtils* utils );

public slots:

/**Repaints the canvas map*/
Expand Down Expand Up @@ -437,6 +454,10 @@ class QgsMapCanvas : QGraphicsView
//! @note added in 2.4
void mapUnitsChanged();

//! Emitted when the current layer is changed
//! @note added in 2.8
void currentLayerChanged( QgsMapLayer* layer );

protected:
//! Overridden standard event to be gestures aware
bool event( QEvent * e );
Expand Down
2 changes: 0 additions & 2 deletions src/app/CMakeLists.txt
Expand Up @@ -87,7 +87,6 @@ SET(QGIS_APP_SRCS
qgsmaptoolsplitparts.cpp
qgsmaptoolsvgannotation.cpp
qgsmaptooltextannotation.cpp
qgsmaptoolvertexedit.cpp

nodetool/qgsmaptoolnodetool.cpp
nodetool/qgsselectedfeature.cpp
Expand Down Expand Up @@ -235,7 +234,6 @@ SET (QGIS_APP_MOC_HDRS
qgsmaptoolsimplify.h
qgsmaptoolsplitfeatures.h
qgsmaptoolsplitparts.h
qgsmaptoolvertexedit.h

nodetool/qgsmaptoolnodetool.h
nodetool/qgsselectedfeature.h
Expand Down

0 comments on commit cae4eb3

Please sign in to comment.