Skip to content

Commit

Permalink
Add polygon highlight support
Browse files Browse the repository at this point in the history
  • Loading branch information
PeterPetrik committed May 29, 2018
1 parent f00321a commit 0a99b11
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 41 deletions.
21 changes: 10 additions & 11 deletions src/quickgui/qgsquickfeaturehighlight.cpp
Expand Up @@ -13,6 +13,8 @@
* *
***************************************************************************/

#include <memory>

#include "qgsvectorlayer.h"

#include "qgsquickfeaturemodel.h"
Expand Down Expand Up @@ -64,17 +66,14 @@ QSGNode *QgsQuickFeatureHighlight::updatePaintNode( QSGNode *n, QQuickItem::Upda
QgsCoordinateTransform transf( layer->crs(), mMapSettings->destinationCrs(), mMapSettings->transformContext() );

QgsFeature feature = mModel->feature().feature();
QgsGeometry geom( feature.geometry() );
geom.transform( transf );

// TODO: this is very crude conversion! QgsQuickHighlightsNode should accept any type of geometry
QVector<QgsPoint> points;
for ( auto it = geom.vertices_begin(); it != geom.vertices_end(); ++it )
points.append( *it );

QgsQuickHighlightSGNode *rb = new QgsQuickHighlightSGNode( points, geom.type(), mColor, mWidth );
rb->setFlag( QSGNode::OwnedByParent );
n->appendChildNode( rb );
if ( feature.hasGeometry() )
{
QgsGeometry geom( feature.geometry() );
geom.transform( transf );
std::unique_ptr<QgsQuickHighlightSGNode> rb( new QgsQuickHighlightSGNode( geom, mColor, mWidth ) );
rb->setFlag( QSGNode::OwnedByParent );
n->appendChildNode( rb.release() );
}
}
mDirty = false;

Expand Down
109 changes: 91 additions & 18 deletions src/quickgui/qgsquickhighlightsgnode.cpp
Expand Up @@ -14,33 +14,70 @@
***************************************************************************/

#include "qgsquickhighlightsgnode.h"
#include "qgstessellator.h"
#include "qgsmultipolygon.h"
#include "qgsgeometrycollection.h"
#include "qgsgeometry.h"
#include "qgstriangle.h"


QgsQuickHighlightSGNode::QgsQuickHighlightSGNode( const QVector<QgsPoint> &points,
QgsWkbTypes::GeometryType type,
const QColor &color, qreal width ) : QSGNode()
QgsQuickHighlightSGNode::QgsQuickHighlightSGNode( const QgsGeometry &geom,
const QColor &color, float width )
: QSGNode()
, mWidth( width )
{
mMaterial.setColor( color );
handleGeometryCollection( geom );
}

void QgsQuickHighlightSGNode::handleGeometryCollection( const QgsGeometry &geom )
{
const QgsGeometryCollection *collection = qgsgeometry_cast<const QgsGeometryCollection *>( geom.constGet() );
if ( collection && !collection->isEmpty() )
{
for ( int i = 0; i < collection->numGeometries(); ++i )
{
QgsGeometry geomN( collection->geometryN( i )->clone() );
handleSingleGeometry( geomN );
}
}
else
{
handleSingleGeometry( geom );
}
}

// TODO: support multi-part geometries
switch ( type )
void QgsQuickHighlightSGNode::handleSingleGeometry( const QgsGeometry &geom )
{
Q_ASSERT( !geom.isMultipart() );

switch ( geom.type() )
{
case QgsWkbTypes::PointGeometry:
{
QVector<QgsPoint> points;
for ( auto it = geom.vertices_begin(); it != geom.vertices_end(); ++it )
points.append( *it );

if ( !points.isEmpty() )
appendChildNode( createPointGeometry( points.at( 0 ), width ) );
appendChildNode( createPointGeometry( points.at( 0 ) ) );
break;
}

case QgsWkbTypes::LineGeometry:
{
appendChildNode( createLineGeometry( points, width ) );
QVector<QgsPoint> points;
for ( auto it = geom.vertices_begin(); it != geom.vertices_end(); ++it )
points.append( *it );

appendChildNode( createLineGeometry( points ) );
break;
}

case QgsWkbTypes::PolygonGeometry:
{
// TODO: support polygon geometries
const QgsPolygon *poly = qgsgeometry_cast<const QgsPolygon *>( geom.constGet() );
if ( poly )
appendChildNode( createPolygonGeometry( *poly ) );
break;
}

Expand All @@ -50,7 +87,7 @@ QgsQuickHighlightSGNode::QgsQuickHighlightSGNode( const QVector<QgsPoint> &point
}
}

QSGGeometryNode *QgsQuickHighlightSGNode::createLineGeometry( const QVector<QgsPoint> &points, qreal width )
QSGGeometryNode *QgsQuickHighlightSGNode::createLineGeometry( const QVector<QgsPoint> &points )
{
std::unique_ptr<QSGGeometryNode> node = qgis::make_unique< QSGGeometryNode>();
std::unique_ptr<QSGGeometry> sgGeom = qgis::make_unique< QSGGeometry>( QSGGeometry::defaultAttributes_Point2D(), points.count() );
Expand All @@ -59,10 +96,13 @@ QSGGeometryNode *QgsQuickHighlightSGNode::createLineGeometry( const QVector<QgsP
int i = 0;
for ( const QgsPoint &pt : points )
{
vertices[i++].set( pt.x(), pt.y() );
vertices[i++].set(
static_cast< float >( pt.x() ),
static_cast< float >( pt.y() )
);
}

sgGeom->setLineWidth( width );
sgGeom->setLineWidth( mWidth );
sgGeom->setDrawingMode( GL_LINE_STRIP );
node->setGeometry( sgGeom.release() );
node->setMaterial( &mMaterial );
Expand All @@ -71,15 +111,18 @@ QSGGeometryNode *QgsQuickHighlightSGNode::createLineGeometry( const QVector<QgsP
return node.release();
}

QSGGeometryNode *QgsQuickHighlightSGNode::createPointGeometry( const QgsPoint &point, qreal width )
QSGGeometryNode *QgsQuickHighlightSGNode::createPointGeometry( const QgsPoint &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( point.x(), point.y() );
vertices[0].set(
static_cast< float >( point.x() ),
static_cast< float >( point.y() )
);
sgGeom->setDrawingMode( GL_POINTS );
sgGeom->setLineWidth( width );
sgGeom->setLineWidth( mWidth );

node->setGeometry( sgGeom.release() );
node->setMaterial( &mMaterial );
Expand All @@ -88,8 +131,38 @@ QSGGeometryNode *QgsQuickHighlightSGNode::createPointGeometry( const QgsPoint &p
return node.release();
}

QSGGeometryNode *QgsQuickHighlightSGNode::createPolygonGeometry( const QVector<QgsPoint> &points )
QSGGeometryNode *QgsQuickHighlightSGNode::createPolygonGeometry( const QgsPolygon &polygon )
{
Q_UNUSED( points );
return 0;
QgsRectangle bounds = polygon.boundingBox();
QgsTessellator tes( bounds.xMinimum(), bounds.yMinimum(), false, false, false );
std::unique_ptr< QgsPolygon > p( qgsgeometry_cast< QgsPolygon * >( polygon.segmentize() ) );
tes.addPolygon( *p.get(), 0.0 );

std::unique_ptr<QgsMultiPolygon> triangles = tes.asMultiPolygon();
int ntris = triangles->numGeometries();

QSGGeometryNode *node = new QSGGeometryNode;
QSGGeometry *sgGeom = new QSGGeometry( QSGGeometry::defaultAttributes_Point2D(), ntris * 3 );

QSGGeometry::Point2D *vertices = sgGeom->vertexDataAsPoint2D();

for ( int j = 0; j < ntris; j++ )
{
const QgsTriangle *triangle = qgsgeometry_cast<const QgsTriangle *>( triangles->geometryN( j ) );
if ( triangle )
{
for ( int v = 0; v < 3; ++v )
{
const QgsPoint vertex = triangle->vertexAt( v );
vertices[3 * j + v].x = static_cast< float >( vertex.x() + bounds.xMinimum() ) ;
vertices[3 * j + v].y = static_cast< float >( vertex.y() + bounds.yMinimum() );
}
}
}
sgGeom->setDrawingMode( GL_TRIANGLES );
node->setGeometry( sgGeom );
node->setMaterial( &mMaterial );
node->setFlag( QSGNode::OwnsGeometry );
node->setFlag( QSGNode::OwnedByParent );
return node;
}
29 changes: 17 additions & 12 deletions src/quickgui/qgsquickhighlightsgnode.h
Expand Up @@ -20,7 +20,7 @@
#include <QtQuick/QSGFlatColorMaterial>

#include "qgspoint.h"
#include "qgswkbtypes.h"
#include "qgsgeometry.h"

#include "qgis_quick.h"

Expand All @@ -29,29 +29,34 @@
*
* This is used to transform (render) QgsGeometry to node for QtQuick scene graph.
*
* Note: support for multi-part geometries and polygons is not implemented
*
* \note QML Type: not exported
*
* \since QGIS 3.2
*/
class QUICK_EXPORT QgsQuickHighlightSGNode : public QSGNode
{
public:
//! Constructor of new QT Quick scene node based on geometry
QgsQuickHighlightSGNode( const QVector<QgsPoint> &points, QgsWkbTypes::GeometryType type, const QColor &color, qreal width );

/**
* 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;

protected:
//! Constructs line geometry from points
QSGGeometryNode *createLineGeometry( const QVector<QgsPoint> &points, qreal width );
//! Constructs point geometry from qgs point
QSGGeometryNode *createPointGeometry( const QgsPoint &point, qreal width );
//! Constructs polygon geometry from points (not implemented)
QSGGeometryNode *createPolygonGeometry( const QVector<QgsPoint> &points );
private:
void handleGeometryCollection( const QgsGeometry &geom );
void handleSingleGeometry( const QgsGeometry &geom );

QSGGeometryNode *createLineGeometry( const QVector<QgsPoint> &points );
QSGGeometryNode *createPointGeometry( const QgsPoint &point );
QSGGeometryNode *createPolygonGeometry( const QgsPolygon &polygon );

QSGFlatColorMaterial mMaterial;
float mWidth;
};

#endif // QGSQUICKHIGHLIGHTSGNODE
Binary file modified tests/testdata/polys.dbf
Binary file not shown.
Binary file modified tests/testdata/polys.shp
Binary file not shown.
Binary file modified tests/testdata/polys.shx
Binary file not shown.

0 comments on commit 0a99b11

Please sign in to comment.