Merge pull request #7105 from PeterPetrik/quick-3-identity

[qgsquick] [feature] Identify and highlight
This commit is contained in:
Matthias Kuhn 2018-06-22 14:34:08 +02:00 committed by GitHub
commit c780d607cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 1461 additions and 17 deletions

View File

@ -0,0 +1,66 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgstessellator.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsTessellator
{
%Docstring
Class that takes care of tessellation of polygons into triangles.
It is expected that client code will create the tessellator object, then repeatedly call
addPolygon() method that will generate triangles, and finally call data() to get final vertex data.
Optionally provides extrusion by adding triangles that serve as walls when extrusion height is non-zero.
.. versionadded:: 3.4
%End
%TypeHeaderCode
#include "qgstessellator.h"
%End
public:
QgsTessellator( double originX, double originY, bool addNormals, bool invertNormals = false, bool addBackFaces = false );
%Docstring
Creates tessellator with a specified origin point of the world (in map coordinates)
%End
void addPolygon( const QgsPolygon &polygon, float extrusionHeight );
%Docstring
Tessellates a triangle and adds its vertex entries to the output data array
%End
QVector<float> data() const;
%Docstring
Returns array of triangle vertex data
Vertice coordinates are stored as (x, z, -y)
%End
int dataVerticesCount() const;
%Docstring
Returns the number of vertices stored in the output data array
%End
int stride() const;
%Docstring
Returns size of one vertex entry in bytes
%End
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgstessellator.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -3,6 +3,7 @@
%Include auto_generated/expression/qgsexpressionnode.sip
%Include auto_generated/expression/qgsexpressionnodeimpl.sip
%Include auto_generated/expression/qgsexpressionfunction.sip
%Include auto_generated/qgstessellator.sip
%Include auto_generated/qgis.sip
%Include auto_generated/qgsaction.sip
%Include auto_generated/qgsactionscope.sip

View File

@ -9,7 +9,6 @@ SET(QGIS_3D_SRCS
qgscameracontroller.cpp
qgsphongmaterialsettings.cpp
qgstessellatedpolygongeometry.cpp
qgstessellator.cpp
qgstilingscheme.cpp
qgsvectorlayer3drenderer.cpp
@ -41,12 +40,6 @@ SET(QGIS_3D_SRCS
terrain/qgsterraintileloader_p.cpp
#terrain/quantizedmeshgeometry.cpp
#terrain/quantizedmeshterraingenerator.cpp
${CMAKE_SOURCE_DIR}/external/poly2tri/common/shapes.cc
${CMAKE_SOURCE_DIR}/external/poly2tri/sweep/advancing_front.cc
${CMAKE_SOURCE_DIR}/external/poly2tri/sweep/cdt.cc
${CMAKE_SOURCE_DIR}/external/poly2tri/sweep/sweep_context.cc
${CMAKE_SOURCE_DIR}/external/poly2tri/sweep/sweep.cc
)
SET(QGIS_3D_MOC_HDRS
@ -82,7 +75,6 @@ SET(QGIS_3D_HDRS
qgscameracontroller.h
qgsphongmaterialsettings.h
qgstessellatedpolygongeometry.h
qgstessellator.h
qgstilingscheme.h
qgsvectorlayer3drenderer.h
@ -127,7 +119,6 @@ INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}/src/core/metadata
${CMAKE_SOURCE_DIR}/src/core/expression
${CMAKE_SOURCE_DIR}/src/core/3d
${CMAKE_SOURCE_DIR}/external/poly2tri
${CMAKE_BINARY_DIR}/src/core
${CMAKE_BINARY_DIR}/src/3d
)

View File

@ -10,6 +10,12 @@ SET(QGIS_CORE_SRCS
${CMAKE_SOURCE_DIR}/external/nmea/time.c
${CMAKE_SOURCE_DIR}/external/nmea/tok.c
${CMAKE_SOURCE_DIR}/external/poly2tri/common/shapes.cc
${CMAKE_SOURCE_DIR}/external/poly2tri/sweep/advancing_front.cc
${CMAKE_SOURCE_DIR}/external/poly2tri/sweep/cdt.cc
${CMAKE_SOURCE_DIR}/external/poly2tri/sweep/sweep_context.cc
${CMAKE_SOURCE_DIR}/external/poly2tri/sweep/sweep.cc
gps/qgsgpsconnection.cpp
gps/qgsgpsconnectionregistry.cpp
gps/qgsgpsdconnection.cpp
@ -291,6 +297,7 @@ SET(QGIS_CORE_SRCS
qgsstringstatisticalsummary.cpp
qgsstringutils.cpp
qgstaskmanager.cpp
qgstessellator.cpp
qgstextlabelfeature.cpp
qgstextrenderer.cpp
qgstolerance.cpp
@ -811,6 +818,8 @@ SET(QGIS_CORE_HDRS
expression/qgsexpressionnodeimpl.h
expression/qgsexpressionfunction.h
qgstessellator.h
qgis.h
qgis_sip.h
qgsaction.h
@ -1204,6 +1213,7 @@ INCLUDE_DIRECTORIES(
metadata
mesh
${CMAKE_SOURCE_DIR}/external/nmea
${CMAKE_SOURCE_DIR}/external/poly2tri
)
IF (WITH_INTERNAL_QEXTSERIALPORT)
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/external/qextserialport)

View File

@ -540,6 +540,11 @@ QgsPoint getPointFromData( QVector< float >::const_iterator &it )
return QgsPoint( x, y, z );
}
int QgsTessellator::dataVerticesCount() const
{
return mData.size() / 3;
}
std::unique_ptr<QgsMultiPolygon> QgsTessellator::asMultiPolygon() const
{
std::unique_ptr< QgsMultiPolygon > mp = qgis::make_unique< QgsMultiPolygon >();

View File

@ -16,16 +16,18 @@
#ifndef QGSTESSELLATOR_H
#define QGSTESSELLATOR_H
#include "qgis_3d.h"
#include "qgis_core.h"
#include "qgis.h"
class QgsPolygon;
class QgsMultiPolygon;
#include <QVector>
#include <memory>
#include "qgspoint.h"
/**
* \ingroup 3d
* \ingroup core
* Class that takes care of tessellation of polygons into triangles.
*
* It is expected that client code will create the tessellator object, then repeatedly call
@ -33,9 +35,9 @@ class QgsMultiPolygon;
*
* Optionally provides extrusion by adding triangles that serve as walls when extrusion height is non-zero.
*
* \since QGIS 3.0
* \since QGIS 3.4 (since QGIS 3.0 in QGIS_3D library)
*/
class _3D_EXPORT QgsTessellator
class CORE_EXPORT QgsTessellator
{
public:
//! Creates tessellator with a specified origin point of the world (in map coordinates)
@ -44,15 +46,23 @@ class _3D_EXPORT QgsTessellator
//! Tessellates a triangle and adds its vertex entries to the output data array
void addPolygon( const QgsPolygon &polygon, float extrusionHeight );
//! Returns array of triangle vertex data
/**
* Returns array of triangle vertex data
*
* Vertice coordinates are stored as (x, z, -y)
*/
QVector<float> data() const { return mData; }
//! Returns the number of vertices stored in the output data array
int dataVerticesCount() const;
//! Returns size of one vertex entry in bytes
int stride() const { return mStride; }
/**
* Returns the triangulation as a multipolygon geometry.
*/
std::unique_ptr< QgsMultiPolygon > asMultiPolygon() const;
std::unique_ptr< QgsMultiPolygon > asMultiPolygon() const SIP_SKIP;
private:
double mOriginX = 0, mOriginY = 0;

View File

@ -1,19 +1,29 @@
############################################################
# sources
SET(QGIS_QUICK_GUI_MOC_HDRS
qgsquickfeaturelayerpair.h
qgsquickfeaturehighlight.h
qgsquickidentifykit.h
qgsquickmapcanvasmap.h
qgsquickmapsettings.h
qgsquickmaptransform.h
qgsquickmessagelogmodel.h
qgsquickscalebarkit.h
qgsquickutils.h
)
SET(QGIS_QUICK_GUI_HDRS
qgsquickhighlightsgnode.h
)
SET(QGIS_QUICK_GUI_SRC
qgsquickfeaturelayerpair.cpp
qgsquickfeaturehighlight.cpp
qgsquickhighlightsgnode.cpp
qgsquickidentifykit.cpp
qgsquickmapcanvasmap.cpp
qgsquickmapsettings.cpp
qgsquickmaptransform.cpp
qgsquickmessagelogmodel.cpp
qgsquickscalebarkit.cpp
qgsquickutils.cpp

View File

@ -29,8 +29,12 @@
#include "qgscoordinatetransformcontext.h"
#include "qgsvectorlayer.h"
#include "qgsquickfeaturehighlight.h"
#include "qgsquickidentifykit.h"
#include "qgsquickfeaturelayerpair.h"
#include "qgsquickmapcanvasmap.h"
#include "qgsquickmapsettings.h"
#include "qgsquickmaptransform.h"
#include "qgsquickmessagelogmodel.h"
#include "qgsquickplugin.h"
#include "qgsquickscalebarkit.h"
@ -53,10 +57,14 @@ void QgsQuickPlugin::registerTypes( const char *uri )
qRegisterMetaType< QgsFeatureId > ( "QgsFeatureId" );
qRegisterMetaType< QgsPoint >( "QgsPoint" );
qRegisterMetaType< QgsPointXY >( "QgsPointXY" );
qRegisterMetaType< QgsQuickFeatureLayerPair >( "QgsQuickFeatureLayerPair" );
qmlRegisterType< QgsProject >( uri, 0, 1, "Project" );
qmlRegisterType< QgsQuickFeatureHighlight >( uri, 0, 1, "FeatureHighlight" );
qmlRegisterType< QgsQuickIdentifyKit >( uri, 0, 1, "IdentifyKit" );
qmlRegisterType< QgsQuickMapCanvasMap >( uri, 0, 1, "MapCanvasMap" );
qmlRegisterType< QgsQuickMapSettings >( uri, 0, 1, "MapSettings" );
qmlRegisterType< QgsQuickMapTransform >( uri, 0, 1, "MapTransform" );
qmlRegisterType< QgsQuickMessageLogModel >( uri, 0, 1, "MessageLogModel" );
qmlRegisterType< QgsQuickScaleBarKit >( uri, 0, 1, "ScaleBarKit" );
qmlRegisterType< QgsVectorLayer >( uri, 0, 1, "VectorLayer" );

View File

@ -0,0 +1,84 @@
/***************************************************************************
qgsqguickfeaturehighlight.cpp
--------------------------------------
Date : May 2018
Copyright : (C) 2018 by Peter Petrik
Email : zilolv 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 <memory>
#include "qgsvectorlayer.h"
#include "qgsquickfeaturehighlight.h"
#include "qgsquickmapsettings.h"
#include "qgsquickhighlightsgnode.h"
QgsQuickFeatureHighlight::QgsQuickFeatureHighlight( QQuickItem *parent )
: QQuickItem( parent )
{
setFlags( QQuickItem::ItemHasContents );
setAntialiasing( true );
// transform to device coords
mTransform.appendToItem( this );
connect( this, &QgsQuickFeatureHighlight::mapSettingsChanged, this, &QgsQuickFeatureHighlight::onMapSettingsChanged );
connect( this, &QgsQuickFeatureHighlight::featureLayerPairChanged, this, &QgsQuickFeatureHighlight::markDirty );
connect( this, &QgsQuickFeatureHighlight::colorChanged, this, &QgsQuickFeatureHighlight::markDirty );
connect( this, &QgsQuickFeatureHighlight::widthChanged, this, &QgsQuickFeatureHighlight::markDirty );
}
void QgsQuickFeatureHighlight::markDirty()
{
mDirty = true;
update();
}
void QgsQuickFeatureHighlight::onMapSettingsChanged()
{
mTransform.setMapSettings( mMapSettings );
markDirty();
}
QSGNode *QgsQuickFeatureHighlight::updatePaintNode( QSGNode *n, QQuickItem::UpdatePaintNodeData * )
{
if ( !mDirty || !mMapSettings || !mFeatureLayerPair.isValid() )
return n;
delete n;
n = new QSGNode;
QgsVectorLayer *layer = mFeatureLayerPair.layer();
Q_ASSERT( layer ); // we checked the validity of feature-layer pair
QgsCoordinateTransform transf( layer->crs(), mMapSettings->destinationCrs(), mMapSettings->transformContext() );
QgsFeature feature = mFeatureLayerPair.feature();
if ( feature.hasGeometry() )
{
QgsGeometry geom( feature.geometry() );
try
{
geom.transform( transf );
std::unique_ptr<QgsQuickHighlightSGNode> rb( new QgsQuickHighlightSGNode( geom, mColor, mWidth ) );
rb->setFlag( QSGNode::OwnedByParent );
n->appendChildNode( rb.release() );
}
catch ( QgsCsException &e )
{
Q_UNUSED( e );
// Caught an error in transform
}
}
mDirty = false;
return n;
}

View File

@ -0,0 +1,99 @@
/***************************************************************************
qgsqguickfeaturehighlight.h
---------------------------
Date : May 2018
Copyright : (C) 2018 by Peter Petrik
Email : zilolv 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. *
* *
***************************************************************************/
#ifndef QGSQUICKFEATUREHIGHLIGHT_H
#define QGSQUICKFEATUREHIGHLIGHT_H
#include <QQuickItem>
#include "qgsquickfeaturelayerpair.h"
#include "qgis_quick.h"
#include "qgsquickmaptransform.h"
class QgsQuickMapSettings;
/**
* \ingroup quick
*
* Creates map highlights for a geometry provided by a FeatureModel.
*
* The highlights are compatible with the QtQuick scene graph and
* can be direcly shown on map canvas
*
* \note QML Type: FeatureHighlight
*
* \since QGIS 3.4
*/
class QUICK_EXPORT QgsQuickFeatureHighlight : public QQuickItem
{
Q_OBJECT
/**
* Associated map settings. Should be initialized from QML component before the first use.
*/
Q_PROPERTY( QgsQuickMapSettings *mapSettings MEMBER mMapSettings NOTIFY mapSettingsChanged )
/**
* Feature to highlight
*/
Q_PROPERTY( QgsQuickFeatureLayerPair featureLayerPair MEMBER mFeatureLayerPair NOTIFY featureLayerPairChanged )
/**
* Color of the highlighted geometry (feature).
*
* Default is yellow color
*/
Q_PROPERTY( QColor color MEMBER mColor NOTIFY colorChanged )
/**
* Pen width of the highlighted geometry (feature).
*
* Default is 20, see QSGGeometry::setLineWidth()
*/
Q_PROPERTY( float width MEMBER mWidth NOTIFY widthChanged )
public:
//! Creates a new feature highlight
explicit QgsQuickFeatureHighlight( QQuickItem *parent = nullptr );
signals:
//! \copydoc QgsQuickFeatureHighlight::featureLayerPair
void featureLayerPairChanged();
//! \copydoc QgsQuickFeatureHighlight::color
void colorChanged();
//! \copydoc QgsQuickFeatureHighlight::width
void widthChanged();
//! \copydoc QgsQuickFeatureHighlight::mapSettings
void mapSettingsChanged();
private slots:
void markDirty();
void onMapSettingsChanged();
private:
QSGNode *updatePaintNode( QSGNode *n, UpdatePaintNodeData * ) override;
QColor mColor = Qt::yellow;
bool mDirty = false;
float mWidth = 20;
QgsQuickFeatureLayerPair mFeatureLayerPair;
QgsQuickMapSettings *mMapSettings = nullptr; // not owned
QgsQuickMapTransform mTransform;
};
#endif // QGSQUICKFEATUREHIGHLIGHT_H

View File

@ -0,0 +1,68 @@
/***************************************************************************
qgsquickfeaturelayerpair.cpp
---------------------
Date : Nov 2017
Copyright : (C) 2017 by Peter Petrik
Email : zilolv 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 "qgsvectorlayer.h"
#include "qgsfeature.h"
#include "qgsquickfeaturelayerpair.h"
QgsQuickFeatureLayerPair::QgsQuickFeatureLayerPair() = default;
QgsQuickFeatureLayerPair::QgsQuickFeatureLayerPair( const QgsFeature &feature, QgsVectorLayer *layer )
: mLayer( layer )
, mFeature( feature )
{
}
QgsVectorLayer *QgsQuickFeatureLayerPair::layer() const
{
return mLayer;
}
QgsFeature QgsQuickFeatureLayerPair::feature() const
{
return mFeature;
}
bool QgsQuickFeatureLayerPair::isValid() const
{
return ( mLayer && mFeature.isValid() && hasValidGeometry() );
}
bool QgsQuickFeatureLayerPair::operator==( const QgsQuickFeatureLayerPair &other ) const
{
return ( mLayer == other.layer() ) && ( mFeature == other.feature() );
}
bool QgsQuickFeatureLayerPair::operator!=( const QgsQuickFeatureLayerPair &other ) const
{
return ( mLayer != other.layer() ) || ( mFeature != other.feature() );
}
bool QgsQuickFeatureLayerPair::hasValidGeometry() const
{
Q_ASSERT( mLayer );
if ( !mFeature.hasGeometry() )
return false;
if ( mFeature.geometry().type() != mLayer->geometryType() )
return false;
if ( QgsWkbTypes::hasZ( mLayer->wkbType() ) != QgsWkbTypes::hasZ( mFeature.geometry().wkbType() ) )
return false;
return true;
}

View File

@ -0,0 +1,102 @@
/***************************************************************************
qgsquickfeaturelayerpair.h
---------------------------
Date : Nov 2017
Copyright : (C) 2017 by Peter Petrik
Email : zilolv 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. *
* *
***************************************************************************/
#ifndef QGSQUICKFEATURELAYERPAIR_H
#define QGSQUICKFEATURELAYERPAIR_H
#include <QObject>
#include "qgsfeature.h"
#include "qgis_quick.h"
class QgsVectorLayer;
/**
* \ingroup quick
* Pair of QgsFeature and QgsVectorLayer
*
* Vector layer is commonly used to gather geometry type or CRS
* for the feature.
*
* Note that the feature may or may not be part of the layer's features
*
* \note QML Type: QgsQuickFeatureLayerPair
*
* \since QGIS 3.4
*/
class QUICK_EXPORT QgsQuickFeatureLayerPair
{
Q_GADGET
/**
* Vector layer to which the feature belongs. May be nullptr if pair is not valid
*
* This is a readonly property.
*/
Q_PROPERTY( QgsVectorLayer *layer READ layer )
/**
* Feature that belongs to layer.
*
* This is a readonly property.
*/
Q_PROPERTY( QgsFeature feature READ feature )
/**
* Whether
* - layer is not nullptr
* - feature is valid
* - feature has geometry and the geometry is the same as geometry expected by layer
*
* This is a readonly property.
*/
Q_PROPERTY( bool valid READ isValid )
public:
//! Constructs invalid feature-layer pair.
QgsQuickFeatureLayerPair();
/**
* Constructor of a new feature-layer pair
* \param feature QgsFeature associated.
* \param layer Vector layer which the feature belongs to
*/
QgsQuickFeatureLayerPair( const QgsFeature &feature, QgsVectorLayer *layer );
//! \copydoc QgsQuickFeatureLayerPair::layer
QgsVectorLayer *layer() const;
//! \copydoc QgsQuickFeatureLayerPair::feature
QgsFeature feature() const;
//! \copydoc QgsQuickFeatureLayerPair::valid
bool isValid() const;
bool operator==( const QgsQuickFeatureLayerPair &other ) const;
bool operator!=( const QgsQuickFeatureLayerPair &other ) const;
private:
bool hasValidGeometry() const;
QgsVectorLayer *mLayer = nullptr; // not owned
QgsFeature mFeature;
};
typedef QList<QgsQuickFeatureLayerPair> QgsQuickFeatureLayerPairs;
Q_DECLARE_METATYPE( QgsQuickFeatureLayerPair )
#endif // QGSQUICKFEATURELAYERPAIR_H

View File

@ -0,0 +1,174 @@
/***************************************************************************
qgsquickhighlightsgnode.cpp
--------------------------------------
Date : Nov 2017
Copyright : (C) 2017 by Matthias Kuhn
Email : matthias@opengis.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. *
* *
***************************************************************************/
#include "qgsquickhighlightsgnode.h"
#include "qgstessellator.h"
#include "qgsgeometrycollection.h"
#include "qgsgeometry.h"
#include "qgslinestring.h"
#include "qgspoint.h"
#include "qgspolygon.h"
QgsQuickHighlightSGNode::QgsQuickHighlightSGNode( const QgsGeometry &geom,
const QColor &color, float width )
: QSGNode()
, mWidth( width )
{
mMaterial.setColor( color );
handleGeometryCollection( geom.constGet(), geom.type() );
}
void QgsQuickHighlightSGNode::handleGeometryCollection( const QgsAbstractGeometry *geom, QgsWkbTypes::GeometryType type )
{
const QgsGeometryCollection *collection = qgsgeometry_cast<const QgsGeometryCollection *>( geom );
if ( collection && !collection->isEmpty() )
{
for ( int i = 0; i < collection->numGeometries(); ++i )
{
const QgsAbstractGeometry *geomN = collection->geometryN( i );
handleSingleGeometry( geomN, type );
}
}
else
{
handleSingleGeometry( geom, type );
}
}
void QgsQuickHighlightSGNode::handleSingleGeometry( const QgsAbstractGeometry *geom, QgsWkbTypes::GeometryType type )
{
switch ( type )
{
case QgsWkbTypes::PointGeometry:
{
const QgsPoint *point = qgsgeometry_cast<const QgsPoint *>( geom );
if ( point )
appendChildNode( createPointGeometry( point ) );
break;
}
case QgsWkbTypes::LineGeometry:
{
const QgsLineString *line = qgsgeometry_cast<const QgsLineString *>( geom );
if ( line )
appendChildNode( createLineGeometry( line ) );
break;
}
case QgsWkbTypes::PolygonGeometry:
{
const QgsPolygon *poly = qgsgeometry_cast<const QgsPolygon *>( geom );
if ( poly )
appendChildNode( createPolygonGeometry( poly ) );
break;
}
case QgsWkbTypes::UnknownGeometry:
case QgsWkbTypes::NullGeometry:
break;
}
}
QSGGeometryNode *QgsQuickHighlightSGNode::createLineGeometry( const QgsLineString *line )
{
Q_ASSERT( line );
std::unique_ptr<QSGGeometryNode> node = qgis::make_unique< QSGGeometryNode>();
std::unique_ptr<QSGGeometry> sgGeom = qgis::make_unique< QSGGeometry>( QSGGeometry::defaultAttributes_Point2D(), line->numPoints() );
QSGGeometry::Point2D *vertices = sgGeom->vertexDataAsPoint2D();
const double *x = line->xData();
const double *y = line->yData();
for ( int i = 0; i < line->numPoints(); ++i )
{
vertices[i].set(
static_cast< float >( x[i] ),
static_cast< float >( y[i] )
);
}
sgGeom->setLineWidth( mWidth );
sgGeom->setDrawingMode( GL_LINE_STRIP );
node->setGeometry( sgGeom.release() );
node->setMaterial( &mMaterial );
node->setFlag( QSGNode::OwnsGeometry );
node->setFlag( QSGNode::OwnedByParent );
return node.release();
}
QSGGeometryNode *QgsQuickHighlightSGNode::createPointGeometry( const QgsPoint *point )
{
Q_ASSERT( point );
std::unique_ptr<QSGGeometryNode> node = qgis::make_unique< QSGGeometryNode>();
std::unique_ptr<QSGGeometry> sgGeom = qgis::make_unique<QSGGeometry>( QSGGeometry::defaultAttributes_Point2D(), 1 );
QSGGeometry::Point2D *vertices = sgGeom->vertexDataAsPoint2D();
vertices[0].set(
static_cast< float >( point->x() ),
static_cast< float >( point->y() )
);
sgGeom->setDrawingMode( GL_POINTS );
sgGeom->setLineWidth( mWidth );
node->setGeometry( sgGeom.release() );
node->setMaterial( &mMaterial );
node->setFlag( QSGNode::OwnsGeometry );
node->setFlag( QSGNode::OwnedByParent );
return node.release();
}
QSGGeometryNode *QgsQuickHighlightSGNode::createPolygonGeometry( const QgsPolygon *polygon )
{
Q_ASSERT( polygon );
const QgsRectangle bounds = polygon->boundingBox();
QgsTessellator tes( bounds.xMinimum(), bounds.yMinimum(), false, false, false );
tes.addPolygon( *polygon, 0.0 );
QSGGeometryNode *node = new QSGGeometryNode;
QSGGeometry *sgGeom = new QSGGeometry( QSGGeometry::defaultAttributes_Point2D(), tes.dataVerticesCount() );
QSGGeometry::Point2D *vertices = sgGeom->vertexDataAsPoint2D();
// we need to revert translation in tessellator
float translateX = static_cast< float >( bounds.xMinimum() );
float translateY = static_cast< float >( bounds.yMinimum() );
const QVector<float> data = tes.data();
int i = 0;
for ( auto it = data.constBegin(); it != data.constEnd(); )
{
float x = *it;
vertices[i].x = translateX + x;
++it;
++it; // we do not need z coordinate
float y = -( *it );
vertices[i].y = translateY + y;
++it;
++i;
}
sgGeom->setDrawingMode( GL_TRIANGLES );
node->setGeometry( sgGeom );
node->setMaterial( &mMaterial );
node->setFlag( QSGNode::OwnsGeometry );
node->setFlag( QSGNode::OwnedByParent );
return node;
}

View File

@ -0,0 +1,65 @@
/***************************************************************************
qgsquickhighlightsgnode.h
--------------------------------------
Date : Nov 2017
Copyright : (C) 2017 by Matthias Kuhn
Email : matthias@opengis.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 QGSQUICKHIGHLIGHTSGNODE_H
#define QGSQUICKHIGHLIGHTSGNODE_H
#include <QtQuick/QSGNode>
#include <QtQuick/QSGFlatColorMaterial>
#include "qgsgeometry.h"
#include "qgis_quick.h"
class QgsLineString;
class QgsPoint;
class QgsPolygon;
/**
* \ingroup quick
*
* This is used to transform (render) QgsGeometry to node for QtQuick scene graph.
*
* \note QML Type: not exported
*
* \since QGIS 3.4
*/
class QUICK_EXPORT QgsQuickHighlightSGNode : public QSGNode
{
public:
/**
* Constructor of new QT Quick scene node based on geometry
*
* \param geom Geometry to render in the map coordinates
* \param color color used to render geom
* \param width width of pen, see QSGGeometry::setLineWidth()
*/
QgsQuickHighlightSGNode( const QgsGeometry &geom, const QColor &color, float width );
//! Destructor
~QgsQuickHighlightSGNode() = default;
private:
void handleGeometryCollection( const QgsAbstractGeometry *geom, QgsWkbTypes::GeometryType type );
void handleSingleGeometry( const QgsAbstractGeometry *geom, QgsWkbTypes::GeometryType type );
QSGGeometryNode *createLineGeometry( const QgsLineString *line );
QSGGeometryNode *createPointGeometry( const QgsPoint *point );
QSGGeometryNode *createPolygonGeometry( const QgsPolygon *polygon );
QSGFlatColorMaterial mMaterial;
float mWidth = 20;
};
#endif // QGSQUICKHIGHLIGHTSGNODE

View File

@ -0,0 +1,259 @@
/***************************************************************************
qgsquickidentifykit.cpp
---------------------
Date : 30.8.2016
Copyright : (C) 2016 by Matthias Kuhn
Email : matthias (at) opengis.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. *
* *
***************************************************************************/
#include "qgsmessagelog.h"
#include "qgsproject.h"
#include "qgslogger.h"
#include "qgsrenderer.h"
#include "qgsvectorlayer.h"
#include "qgsquickidentifykit.h"
#include "qgsquickmapsettings.h"
#include "qgis.h"
QgsQuickIdentifyKit::QgsQuickIdentifyKit( QObject *parent )
: QObject( parent )
{
}
QgsQuickMapSettings *QgsQuickIdentifyKit::mapSettings() const
{
return mMapSettings;
}
void QgsQuickIdentifyKit::setMapSettings( QgsQuickMapSettings *mapSettings )
{
if ( mapSettings == mMapSettings )
return;
mMapSettings = mapSettings;
emit mapSettingsChanged();
}
QgsQuickFeatureLayerPairs QgsQuickIdentifyKit::identify( const QPointF &point, QgsVectorLayer *layer )
{
QgsQuickFeatureLayerPairs results;
if ( !mMapSettings )
{
QgsDebugMsg( QStringLiteral( "Unable to use IdentifyKit without mapSettings property set." ) );
return results;
}
QgsPointXY mapPoint = mMapSettings->mapSettings().mapToPixel().toMapCoordinates( point.toPoint() );
if ( layer )
{
QgsFeatureList featureList = identifyVectorLayer( layer, mapPoint );
for ( const QgsFeature &feature : featureList )
{
results.append( QgsQuickFeatureLayerPair( feature, layer ) );
}
QgsDebugMsg( QStringLiteral( "IdentifyKit identified %1 results for layer %2" ).arg( results.count() ).arg( layer->name() ) );
}
else
{
QStringList noIdentifyLayerIdList;
if ( mMapSettings->project() )
{
noIdentifyLayerIdList = mMapSettings->project()->nonIdentifiableLayers();
}
for ( QgsMapLayer *layer : mMapSettings->mapSettings().layers() )
{
if ( mMapSettings->project() && noIdentifyLayerIdList.contains( layer->id() ) )
continue;
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer );
if ( vl )
{
QgsFeatureList featureList = identifyVectorLayer( vl, mapPoint );
for ( const QgsFeature &feature : featureList )
{
results.append( QgsQuickFeatureLayerPair( feature, vl ) );
}
}
}
QgsDebugMsg( QStringLiteral( "IdentifyKit identified %1 results" ).arg( results.count() ) );
}
return results;
}
static QgsQuickFeatureLayerPair _closestFeature( const QgsQuickFeatureLayerPairs &results, const QgsMapSettings &mapSettings, const QPointF &point )
{
QgsPointXY mapPoint = mapSettings.mapToPixel().toMapCoordinates( point.toPoint() );
QgsGeometry mapPointGeom( QgsGeometry::fromPointXY( mapPoint ) );
double distMin = 1e10;
int iMin = -1;
for ( int i = 0; i < results.count(); ++i )
{
const QgsQuickFeatureLayerPair &res = results.at( i );
QgsGeometry geom( res.feature().geometry() );
try
{
geom.transform( mapSettings.layerTransform( res.layer() ) );
}
catch ( QgsCsException &e )
{
Q_UNUSED( e );
// Caught an error in transform
continue;
}
double dist = geom.distance( mapPointGeom );
if ( dist < distMin )
{
iMin = i;
distMin = dist;
}
}
if ( results.empty() )
{
return QgsQuickFeatureLayerPair();
}
else
{
return results.at( iMin );
}
}
QgsQuickFeatureLayerPair QgsQuickIdentifyKit::identifyOne( const QPointF &point, QgsVectorLayer *layer )
{
QgsQuickFeatureLayerPairs results = identify( point, layer );
return _closestFeature( results, mMapSettings->mapSettings(), point );
}
QgsFeatureList QgsQuickIdentifyKit::identifyVectorLayer( QgsVectorLayer *layer, const QgsPointXY &point ) const
{
QgsFeatureList results;
if ( !layer || !layer->isSpatial() )
return results;
if ( !layer->isInScaleRange( mMapSettings->mapSettings().scale() ) )
return results;
QgsFeatureList featureList;
// toLayerCoordinates will throw an exception for an 'invalid' point.
// For example, if you project a world map onto a globe using EPSG 2163
// and then click somewhere off the globe, an exception will be thrown.
try
{
// create the search rectangle
double searchRadius = searchRadiusMU();
QgsRectangle r;
r.setXMinimum( point.x() - searchRadius );
r.setXMaximum( point.x() + searchRadius );
r.setYMinimum( point.y() - searchRadius );
r.setYMaximum( point.y() + searchRadius );
r = toLayerCoordinates( layer, r );
QgsFeatureRequest req;
req.setFilterRect( r );
req.setLimit( mFeaturesLimit );
req.setFlags( QgsFeatureRequest::ExactIntersect );
QgsFeatureIterator fit = layer->getFeatures( req );
QgsFeature f;
while ( fit.nextFeature( f ) )
featureList << QgsFeature( f );
}
catch ( QgsCsException &cse )
{
QgsDebugMsg( tr( "Invalid point and proceed with no features found." ) );
Q_UNUSED( cse );
}
bool filter = false;
QgsRenderContext context( QgsRenderContext::fromMapSettings( mMapSettings->mapSettings() ) );
context.expressionContext() << QgsExpressionContextUtils::layerScope( layer );
QgsFeatureRenderer *renderer = layer->renderer();
if ( renderer && renderer->capabilities() & QgsFeatureRenderer::ScaleDependent )
{
// setup scale for scale dependent visibility (rule based)
renderer->startRender( context, layer->fields() );
filter = renderer->capabilities() & QgsFeatureRenderer::Filter;
}
for ( const QgsFeature &feature : featureList )
{
context.expressionContext().setFeature( feature );
if ( filter && !renderer->willRenderFeature( const_cast<QgsFeature &>( feature ), context ) )
continue;
results.append( feature );
}
if ( renderer && renderer->capabilities() & QgsFeatureRenderer::ScaleDependent )
{
renderer->stopRender( context );
}
return results;
}
double QgsQuickIdentifyKit::searchRadiusMU( const QgsRenderContext &context ) const
{
return mSearchRadiusMm * context.scaleFactor() * context.mapToPixel().mapUnitsPerPixel();
}
double QgsQuickIdentifyKit::searchRadiusMU() const
{
QgsRenderContext context = QgsRenderContext::fromMapSettings( mMapSettings->mapSettings() );
return searchRadiusMU( context );
}
QgsRectangle QgsQuickIdentifyKit::toLayerCoordinates( QgsMapLayer *layer, const QgsRectangle &rect ) const
{
return mMapSettings->mapSettings().mapToLayerCoordinates( layer, rect );
}
double QgsQuickIdentifyKit::searchRadiusMm() const
{
return mSearchRadiusMm;
}
void QgsQuickIdentifyKit::setSearchRadiusMm( double searchRadiusMm )
{
if ( qgsDoubleNear( mSearchRadiusMm, searchRadiusMm ) )
return;
mSearchRadiusMm = searchRadiusMm;
emit searchRadiusMmChanged();
}
int QgsQuickIdentifyKit::featuresLimit() const
{
return mFeaturesLimit;
}
void QgsQuickIdentifyKit::setFeaturesLimit( int limit )
{
if ( mFeaturesLimit == limit )
return;
mFeaturesLimit = limit;
emit featuresLimitChanged();
}

View File

@ -0,0 +1,139 @@
/***************************************************************************
qgsquickidentifykit.h
---------------------
Date : 30.8.2016
Copyright : (C) 2016 by Matthias Kuhn
Email : matthias (at) opengis.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 QGSQUICKIDENTIFYKIT_H
#define QGSQUICKIDENTIFYKIT_H
#include <QObject>
#include <QPair>
#include "qgsfeature.h"
#include "qgsmapsettings.h"
#include "qgspoint.h"
#include "qgsrendercontext.h"
#include "qgis_quick.h"
#include "qgsquickfeaturelayerpair.h"
class QgsMapLayer;
class QgsQuickMapSettings;
class QgsVectorLayer;
/**
* \ingroup quick
*
* Convenient set of tools to identify features
*
* - get a list of features in a defined radius from a point.
* - get a feature with the closest distance to the point
*
* \note QML Type: IdentifyKit
*
* \since QGIS 3.4
*/
class QUICK_EXPORT QgsQuickIdentifyKit : public QObject
{
Q_OBJECT
/**
* Map settings. Set directly when creating QML object.
*/
Q_PROPERTY( QgsQuickMapSettings *mapSettings READ mapSettings WRITE setMapSettings NOTIFY mapSettingsChanged )
/**
* Search radius for the identify functions
*
* Default is 8.
*/
Q_PROPERTY( double searchRadiusMm READ searchRadiusMm WRITE setSearchRadiusMm NOTIFY searchRadiusMmChanged )
/**
* Maximum number of features returned from the QgsQuickIdentifyKit::identify()
*
* Default is 100.
*/
Q_PROPERTY( int featuresLimit READ featuresLimit WRITE setFeaturesLimit NOTIFY featuresLimitChanged )
public:
//! Constructor of new identify kit.
explicit QgsQuickIdentifyKit( QObject *parent = nullptr );
//! \copydoc QgsQuickIdentifyKit::mapSettings
QgsQuickMapSettings *mapSettings() const;
//! \copydoc QgsQuickIdentifyKit::mapSettings
void setMapSettings( QgsQuickMapSettings *mapSettings );
//! \copydoc QgsQuickIdentifyKit::searchRadiusMm
double searchRadiusMm() const;
//! \copydoc QgsQuickIdentifyKit::searchRadiusMm
void setSearchRadiusMm( double searchRadiusMm );
//! \copydoc QgsQuickIdentifyKit::featuresLimit
int featuresLimit() const;
//! \copydoc QgsQuickIdentifyKit::featuresLimit
void setFeaturesLimit( int limit );
/**
* Gets the closest feature to the point within the search radius
*
* If layer is nullptr, identifies the closest feature from all identifiable layers
* If layer is not nullptr, identifies the closest feature from given layer
*
* To modify search radius, use QgsQuickIdentifyKit::searchRadiusMm
*
* \param point position to search a feature from
* \param layer if defined, search for a feature only from this layer
*/
Q_INVOKABLE QgsQuickFeatureLayerPair identifyOne( const QPointF &point, QgsVectorLayer *layer = nullptr );
/**
* Gets all features in the search radius
*
* If layer is nullptr, identifies features from all identifiable layers
* If layer is not nullptr, identifies only features from given layer
*
* To limit number of results, use QgsQuickIdentifyKit::featuresLimit
* To modify search radius, use QgsQuickIdentifyKit::searchRadiusMm
*
* \param point position to search features ob
* \param layer if defined, search for features only from this layer
*/
Q_INVOKABLE QgsQuickFeatureLayerPairs identify( const QPointF &point, QgsVectorLayer *layer = nullptr );
signals:
//! \copydoc QgsQuickIdentifyKit::mapSettings
void mapSettingsChanged();
//! \copydoc QgsQuickIdentifyKit::searchRadiusMm
void searchRadiusMmChanged();
//! \copydoc QgsQuickIdentifyKit::featuresLimit
void featuresLimitChanged();
private:
QgsQuickMapSettings *mMapSettings = nullptr; // not owned
double searchRadiusMU( const QgsRenderContext &context ) const;
double searchRadiusMU() const;
QgsRectangle toLayerCoordinates( QgsMapLayer *layer, const QgsRectangle &rect ) const;
QgsFeatureList identifyVectorLayer( QgsVectorLayer *layer, const QgsPointXY &point ) const;
double mSearchRadiusMm = 8;
int mFeaturesLimit = 100;
};
#endif // QGSQUICKIDENTIFYKIT_H

View File

@ -0,0 +1,57 @@
/***************************************************************************
qgsquickmaptransform.cpp
--------------------------------------
Date : 27.12.2014
Copyright : (C) 2014 by Matthias Kuhn
Email : matthias (at) opengis.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. *
* *
***************************************************************************/
#include "qgsquickmaptransform.h"
#include "qgsquickmapsettings.h"
void QgsQuickMapTransform::applyTo( QMatrix4x4 *matrix ) const
{
*matrix *= mMatrix;
matrix->optimize();
}
QgsQuickMapSettings *QgsQuickMapTransform::mapSettings() const
{
return mMapSettings;
}
void QgsQuickMapTransform::setMapSettings( QgsQuickMapSettings *mapSettings )
{
if ( mapSettings == mMapSettings )
return;
if ( mMapSettings )
disconnect( mMapSettings, &QgsQuickMapSettings::visibleExtentChanged, this, &QgsQuickMapTransform::updateMatrix );
mMapSettings = mapSettings;
if ( mMapSettings )
connect( mMapSettings, &QgsQuickMapSettings::visibleExtentChanged, this, &QgsQuickMapTransform::updateMatrix );
emit mapSettingsChanged();
}
void QgsQuickMapTransform::updateMatrix()
{
QMatrix4x4 matrix;
float scaleFactor = static_cast<float>( 1.0 / mMapSettings->mapUnitsPerPixel() );
matrix.scale( scaleFactor, -scaleFactor );
matrix.translate( static_cast<float>( -mMapSettings->visibleExtent().xMinimum( ) ),
static_cast<float>( -mMapSettings->visibleExtent().yMaximum() ) );
mMatrix = matrix;
update();
}

View File

@ -0,0 +1,77 @@
/***************************************************************************
qgsquickmaptransform.h
--------------------------------------
Date : 27.12.2014
Copyright : (C) 2014 by Matthias Kuhn
Email : matthias (at) opengis.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 QGSQUICKMAPTRANSFORM_H
#define QGSQUICKMAPTRANSFORM_H
#include <QQuickItem>
#include <QMatrix4x4>
#include "qgis_quick.h"
class QgsQuickMapSettings;
/**
* \ingroup quick
* The QgsQuickMapTransform is transformation that can be attached to any QQuickItem.
*
* If the item is based on the map coordinates, QgsQuickMapTransform will
* transform it to the device coordintes based on the attached map settings.
*
* \note QML Type: MapTransform
*
* \since QGIS 3.4
*/
class QUICK_EXPORT QgsQuickMapTransform : public QQuickTransform
{
Q_OBJECT
/**
* Associated map settings. Should be initialized before the first use from mapcanvas map settings.
*/
Q_PROPERTY( QgsQuickMapSettings *mapSettings READ mapSettings WRITE setMapSettings NOTIFY mapSettingsChanged )
public:
//! create new map transform
QgsQuickMapTransform() = default;
~QgsQuickMapTransform() = default;
/**
* Apply transformation based on current map settings to a matrix.
*
* Also optimize resulting matrix after transformation
* \param matrix Matrix to be transformed
*/
void applyTo( QMatrix4x4 *matrix ) const;
//! \copydoc QgsQuickMapTransform::mapSettings
QgsQuickMapSettings *mapSettings() const;
//! \copydoc QgsQuickMapTransform::mapSettings
void setMapSettings( QgsQuickMapSettings *mapSettings );
signals:
//! \copydoc QgsQuickMapTransform::mapSettings
void mapSettingsChanged();
private slots:
void updateMatrix();
private:
QgsQuickMapSettings *mMapSettings = nullptr;
QMatrix4x4 mMatrix;
};
#endif // QGSQUICKMAPTRANSFORM_H

View File

@ -18,7 +18,9 @@
#include "qgis.h"
#include "qgsdistancearea.h"
#include "qgslogger.h"
#include "qgsvectorlayer.h"
#include "qgsquickfeaturelayerpair.h"
#include "qgsquickmapsettings.h"
#include "qgsquickutils.h"
#include "qgsunittypes.h"
@ -52,6 +54,11 @@ void QgsQuickUtils::logMessage( const QString &message, const QString &tag, Qgis
QgsMessageLog::logMessage( message, tag, level );
}
QgsQuickFeatureLayerPair QgsQuickUtils::featureFactory( const QgsFeature &feature, QgsVectorLayer *layer ) const
{
return QgsQuickFeatureLayerPair( feature, layer );
}
QString QgsQuickUtils::dumpScreenInfo() const
{
QRect rec = QApplication::desktop()->screenGeometry();

View File

@ -24,8 +24,11 @@
#include "qgsmessagelog.h"
#include "qgsquickmapsettings.h"
#include "qgsquickfeaturelayerpair.h"
#include "qgis_quick.h"
#include "qgsfeature.h"
class QgsVectorLayer;
class QgsCoordinateReferenceSystem;
/**
@ -73,6 +76,15 @@ class QUICK_EXPORT QgsQuickUtils: public QObject
const QString &tag = QString( "QgsQuick" ),
Qgis::MessageLevel level = Qgis::Warning );
/**
* QgsQuickFeatureLayerPair factory for tuple of QgsFeature and QgsVectorLayer used in QgsQUick library.
* \param feature QgsFeature linked to new QgsQuickFeature instance.
* \param layer QgsVectorLayer which the feature belongs to, optional.
*
* \since QGIS 3.4
*/
Q_INVOKABLE QgsQuickFeatureLayerPair featureFactory( const QgsFeature &feature, QgsVectorLayer *layer = nullptr ) const;
/**
* Returns a string with information about screen size and resolution
*

View File

@ -78,6 +78,7 @@ ENDMACRO (ADD_QGIS_TEST)
#############################################################
# Tests:
ADD_QGIS_TEST(qgsquickidentifykit testqgsquickidentifykit.cpp)
ADD_QGIS_TEST(qgsquickutils testqgsquickutils.cpp)
ADD_QGIS_TEST(qgsquickscalebarkit testqgsquickscalebarkit.cpp)

View File

@ -32,12 +32,26 @@ ApplicationWindow {
mapSettings.project: __project
mapSettings.layers: __layers
QgsQuick.IdentifyKit {
id: identifyKit
mapSettings: mapCanvas.mapSettings
}
onClicked: {
var screenPoint = Qt.point(mouse.x, mouse.y)
console.log("clicked:" + screenPoint)
var res = identifyKit.identifyOne(screenPoint);
highlight.featureLayerPair = res
}
}
QgsQuick.FeatureHighlight {
anchors.fill: mapCanvas
id: highlight
color: "red"
mapSettings: mapCanvas.mapSettings
z: 1
}
Drawer {
id: logPanel
visible: true

View File

@ -0,0 +1,185 @@
/***************************************************************************
testqgsquickidentifykit.cpp.cpp
--------------------------------------
Date : May 2018
Copyright : (C) 2018 by Viktor Sklencar
Email : vsklencar 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 <QObject>
#include <QApplication>
#include <QDesktopWidget>
#include "qgsapplication.h"
#include "qgstest.h"
#include "qgis.h"
#include "qgsvectorlayer.h"
#include "qgsfeature.h"
#include "qgsgeometry.h"
#include "qgsvectordataprovider.h"
#include "qgsquickmapcanvasmap.h"
#include "qgsquickidentifykit.h"
class TestQgsQuickScaleBarKit: public QObject
{
Q_OBJECT
private slots:
void init() {} // will be called before each testfunction is executed.
void cleanup() {} // will be called after every testfunction.
void identifyOne(); // tests identifyOne function without given layer
void identifyOneDefinedVector(); // tests identifyOne function with given layer
void identifyInRadius();
};
void TestQgsQuickScaleBarKit::identifyOne()
{
QgsCoordinateReferenceSystem crsGPS = QgsCoordinateReferenceSystem::fromEpsgId( 4326 );
QVERIFY( crsGPS.authid() == "EPSG:4326" );
QgsRectangle extent = QgsRectangle( -120, 23, -82, 47 );
QgsQuickMapCanvasMap canvas;
QgsVectorLayer *tempLayer = new QgsVectorLayer( QStringLiteral( "Point?crs=epsg:4326" ), QStringLiteral( "vl" ), QStringLiteral( "memory" ) );
QVERIFY( tempLayer->isValid() );
QgsQuickMapSettings *ms = canvas.mapSettings();
ms->setDestinationCrs( crsGPS );
ms->setExtent( extent );
ms->setOutputSize( QSize( 1000, 500 ) );
ms->setLayers( QList<QgsMapLayer *>() << tempLayer );
QgsQuickIdentifyKit kit;
kit.setMapSettings( ms );
double pointX = -31.208;
double pointY = 20.407999999999998;
double pointX2 = pointX + 1;
// add feature
QgsFeature f1( tempLayer->dataProvider()->fields(), 1 );
QgsPointXY point( pointX, pointY );
QgsGeometry geom = QgsGeometry::fromPointXY( point ) ;
f1.setGeometry( geom );
// add another feature
QgsFeature f2( tempLayer->dataProvider()->fields(), 1 );
QgsPointXY point2( pointX2, pointY );
QgsGeometry geom2 = QgsGeometry::fromPointXY( point2 ) ;
f2.setGeometry( geom2 );
tempLayer->dataProvider()->addFeatures( QgsFeatureList() << f1 << f2 );
// exactly matches f1 point
QgsPointXY screenPoint( 1954.0, 554.0 );
QgsQuickFeatureLayerPair identifiedFeature = kit.identifyOne( screenPoint.toQPointF() );
QVERIFY( identifiedFeature.isValid() );
QVERIFY( identifiedFeature.feature().geometry().asPoint() == point );
}
void TestQgsQuickScaleBarKit::identifyOneDefinedVector()
{
QgsCoordinateReferenceSystem crsGPS = QgsCoordinateReferenceSystem::fromEpsgId( 4326 );
QVERIFY( crsGPS.authid() == "EPSG:4326" );
QgsRectangle extent = QgsRectangle( -120, 23, -82, 47 );
QgsQuickMapCanvasMap canvas;
QgsVectorLayer *tempLayer = new QgsVectorLayer( QStringLiteral( "Point?crs=epsg:4326" ), QStringLiteral( "vl" ), QStringLiteral( "memory" ) );
QVERIFY( tempLayer->isValid() );
QgsVectorLayer *tempLayer2 = new QgsVectorLayer( QStringLiteral( "Point?crs=epsg:4326" ), QStringLiteral( "vl2" ), QStringLiteral( "memory" ) );
QVERIFY( tempLayer->isValid() );
QgsQuickMapSettings *ms = canvas.mapSettings();
ms->setDestinationCrs( crsGPS );
ms->setExtent( extent );
ms->setOutputSize( QSize( 1000, 500 ) );
ms->setLayers( QList<QgsMapLayer *>() << tempLayer );
QgsQuickIdentifyKit kit;
kit.setMapSettings( ms );
double pointX = -31.208;
double pointY = 20.407999999999998;
double pointX2 = pointX + 1;
// add feature
QgsFeature f1( tempLayer->dataProvider()->fields(), 1 );
QgsPointXY point( pointX, pointY );
QgsGeometry geom = QgsGeometry::fromPointXY( point ) ;
f1.setGeometry( geom );
// add another feature
QgsFeature f2( tempLayer2->dataProvider()->fields(), 1 );
QgsPointXY point2( pointX2, pointY );
QgsGeometry geom2 = QgsGeometry::fromPointXY( point2 ) ;
f2.setGeometry( geom2 );
tempLayer->dataProvider()->addFeatures( QgsFeatureList() << f1 );
tempLayer2->dataProvider()->addFeatures( QgsFeatureList() << f2 );
QgsPointXY screenPoint( 1954.0, 554.0 );
QgsQuickFeatureLayerPair identifiedFeature = kit.identifyOne( screenPoint.toQPointF(), tempLayer2 );
QVERIFY( identifiedFeature.isValid() );
QVERIFY( identifiedFeature.feature().geometry().asPoint() == point2 );
}
void TestQgsQuickScaleBarKit::identifyInRadius()
{
QgsCoordinateReferenceSystem crsGPS = QgsCoordinateReferenceSystem::fromEpsgId( 4326 );
QVERIFY( crsGPS.authid() == "EPSG:4326" );
QgsRectangle extent = QgsRectangle( -120, 23, -82, 47 );
QgsQuickMapCanvasMap canvas;
QgsVectorLayer *tempLayer = new QgsVectorLayer( QStringLiteral( "Point?crs=epsg:4326" ), QStringLiteral( "vl" ), QStringLiteral( "memory" ) );
QVERIFY( tempLayer->isValid() );
QgsQuickMapSettings *ms = canvas.mapSettings();
ms->setDestinationCrs( crsGPS );
ms->setExtent( extent );
ms->setOutputSize( QSize( 1000, 500 ) );
ms->setLayers( QList<QgsMapLayer *>() << tempLayer );
QgsQuickIdentifyKit kit;
kit.setMapSettings( ms );
double pointX = -31.208;
double pointY = 20.407999999999998;
double pointX2 = pointX + 5;
QgsFeature f1( tempLayer->dataProvider()->fields(), 1 );
QgsPointXY point( pointX, pointY );
QgsGeometry geom = QgsGeometry::fromPointXY( point ) ;
f1.setGeometry( geom );
QgsFeature f2( tempLayer->dataProvider()->fields(), 1 );
QgsPointXY point2( pointX2, pointY );
QgsGeometry geom2 = QgsGeometry::fromPointXY( point2 ) ;
f2.setGeometry( geom2 );
tempLayer->dataProvider()->addFeatures( QgsFeatureList() << f1 << f2 );
kit.setSearchRadiusMm( 1.0 );
QgsPointXY screenPoint( 1954.0, 554.0 );
QgsQuickFeatureLayerPairs res = kit.identify( screenPoint.toQPointF() );
QVERIFY( res.size() == 1 );
kit.setSearchRadiusMm( 100.0 );
res = kit.identify( screenPoint.toQPointF() );
QVERIFY( res.size() == 2 );
}
QGSTEST_MAIN( TestQgsQuickScaleBarKit )
#include "testqgsquickidentifykit.moc"

View File

@ -59,7 +59,7 @@ void TestQgsQuickUtils::screenUnitsToMeters()
ms.setExtent( QgsRectangle( 49, 16, 50, 17 ) );
ms.setOutputSize( QSize( 1000, 500 ) );
double sutm = utils.screenUnitsToMeters( &ms, 1 );
QVERIFY( fabs( sutm - 213 ) < 1.0 );
QGSCOMPARENEAR( sutm, 213, 1.0 );
}
QGSTEST_MAIN( TestQgsQuickUtils )