Skip to content

Commit

Permalink
line poly items
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Aug 5, 2020
1 parent c5532d0 commit fbad4e3
Show file tree
Hide file tree
Showing 3 changed files with 285 additions and 1 deletion.
218 changes: 218 additions & 0 deletions src/core/annotations/qgsannotationitem.cpp
Expand Up @@ -110,3 +110,221 @@ void QgsMarkerItem::setSymbol( QgsMarkerSymbol *symbol )
{
mSymbol.reset( symbol );
}




QgsLineStringItem::QgsLineStringItem( const QgsLineString &linestring, const QgsCoordinateReferenceSystem &crs )
: QgsAnnotationItem( crs )
, mLineString( linestring )
, mSymbol( qgis::make_unique< QgsLineSymbol >() )
{

}

QgsLineStringItem::~QgsLineStringItem() = default;

QString QgsLineStringItem::type() const
{
return QStringLiteral( "linestring" );
}

void QgsLineStringItem::render( QgsRenderContext &context, QgsFeedback * )
{
QPolygonF pts = mLineString.asQPolygonF();

//transform the QPolygonF to screen coordinates
if ( context.coordinateTransform().isValid() )
{
try
{
context.coordinateTransform().transformPolygon( pts );
}
catch ( QgsCsException & )
{
// we don't abort the rendering here, instead we remove any invalid points and just plot those which ARE valid
}
}

// remove non-finite points, e.g. infinite or NaN points caused by reprojecting errors
pts.erase( std::remove_if( pts.begin(), pts.end(),
[]( const QPointF point )
{
return !std::isfinite( point.x() ) || !std::isfinite( point.y() );
} ), pts.end() );

QPointF *ptr = pts.data();
for ( int i = 0; i < pts.size(); ++i, ++ptr )
{
context.mapToPixel().transformInPlace( ptr->rx(), ptr->ry() );
}

mSymbol->startRender( context );
mSymbol->renderPolyline( pts, nullptr, context );
mSymbol->stopRender( context );
}

bool QgsLineStringItem::writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const
{
element.setAttribute( QStringLiteral( "wkt" ), mLineString.asWkt() );
crs().writeXml( element, document );

element.appendChild( QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "lineSymbol" ), mSymbol.get(), document, context ) );

return true;
}

QgsLineStringItem *QgsLineStringItem::create()
{
return new QgsLineStringItem( QgsLineString(), QgsCoordinateReferenceSystem() );
}

QgsLineStringItem *QgsLineStringItem::createFromElement( const QDomElement &element, const QgsReadWriteContext &context )
{
const QString wkt = element.attribute( QStringLiteral( "wkt" ) );
QgsLineString ls;
ls.fromWkt( wkt );

QgsCoordinateReferenceSystem crs;
crs.readXml( element );

std::unique_ptr< QgsLineStringItem > item = qgis::make_unique< QgsLineStringItem >( ls, crs );

const QDomElement symbolElem = element.firstChildElement( QStringLiteral( "symbol" ) );
if ( !symbolElem.isNull() )
item->setSymbol( QgsSymbolLayerUtils::loadSymbol< QgsLineSymbol >( symbolElem, context ) );

return item.release();
}

QgsLineStringItem *QgsLineStringItem::clone()
{
std::unique_ptr< QgsLineStringItem > item = qgis::make_unique< QgsLineStringItem >( mLineString, crs() );
item->setSymbol( mSymbol->clone() );
return item.release();
}

const QgsLineSymbol *QgsLineStringItem::symbol() const
{
return mSymbol.get();
}

void QgsLineStringItem::setSymbol( QgsLineSymbol *symbol )
{
mSymbol.reset( symbol );
}



QgsPolygonItem::QgsPolygonItem( const QgsPolygon &polygon, const QgsCoordinateReferenceSystem &crs )
: QgsAnnotationItem( crs )
, mPolygon( polygon )
, mSymbol( qgis::make_unique< QgsFillSymbol >() )
{

}

QgsPolygonItem::~QgsPolygonItem() = default;

QString QgsPolygonItem::type() const
{
return QStringLiteral( "polygon" );
}

void QgsPolygonItem::render( QgsRenderContext &context, QgsFeedback * )
{

auto transformRing = [&context]( QPolygonF & pts )
{
//transform the QPolygonF to screen coordinates
if ( context.coordinateTransform().isValid() )
{
try
{
context.coordinateTransform().transformPolygon( pts );
}
catch ( QgsCsException & )
{
// we don't abort the rendering here, instead we remove any invalid points and just plot those which ARE valid
}
}

// remove non-finite points, e.g. infinite or NaN points caused by reprojecting errors
pts.erase( std::remove_if( pts.begin(), pts.end(),
[]( const QPointF point )
{
return !std::isfinite( point.x() ) || !std::isfinite( point.y() );
} ), pts.end() );

QPointF *ptr = pts.data();
for ( int i = 0; i < pts.size(); ++i, ++ptr )
{
context.mapToPixel().transformInPlace( ptr->rx(), ptr->ry() );
}
};

QPolygonF exterior = mPolygon.exteriorRing()->asQPolygonF();
transformRing( exterior );
QList<QPolygonF> rings;
rings.reserve( mPolygon.numInteriorRings() );
for ( int i = 0; i < mPolygon.numInteriorRings(); ++i )
{
QPolygonF ring = mPolygon.interiorRing( i )->asQPolygonF();
transformRing( ring );
rings.append( ring );
}

mSymbol->startRender( context );
mSymbol->renderPolygon( exterior, rings.empty() ? nullptr : &rings, nullptr, context );
mSymbol->stopRender( context );
}

bool QgsPolygonItem::writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const
{
element.setAttribute( QStringLiteral( "wkt" ), mPolygon.asWkt() );
crs().writeXml( element, document );

element.appendChild( QgsSymbolLayerUtils::saveSymbol( QStringLiteral( "lineSymbol" ), mSymbol.get(), document, context ) );

return true;
}

QgsPolygonItem *QgsPolygonItem::create()
{
return new QgsPolygonItem( QgsPolygon(), QgsCoordinateReferenceSystem() );
}

QgsPolygonItem *QgsPolygonItem::createFromElement( const QDomElement &element, const QgsReadWriteContext &context )
{
const QString wkt = element.attribute( QStringLiteral( "wkt" ) );
QgsPolygon poly;
poly.fromWkt( wkt );

QgsCoordinateReferenceSystem crs;
crs.readXml( element );

std::unique_ptr< QgsPolygonItem > item = qgis::make_unique< QgsPolygonItem >( poly, crs );

const QDomElement symbolElem = element.firstChildElement( QStringLiteral( "symbol" ) );
if ( !symbolElem.isNull() )
item->setSymbol( QgsSymbolLayerUtils::loadSymbol< QgsFillSymbol >( symbolElem, context ) );

return item.release();
}

QgsPolygonItem *QgsPolygonItem::clone()
{
std::unique_ptr< QgsPolygonItem > item = qgis::make_unique< QgsPolygonItem >( mPolygon, crs() );
item->setSymbol( mSymbol->clone() );
return item.release();
}

const QgsFillSymbol *QgsPolygonItem::symbol() const
{
return mSymbol.get();
}

void QgsPolygonItem::setSymbol( QgsFillSymbol *symbol )
{
mSymbol.reset( symbol );
}
63 changes: 63 additions & 0 deletions src/core/annotations/qgsannotationitem.h
Expand Up @@ -21,9 +21,13 @@
#include "qgis_sip.h"
#include "qgscoordinatereferencesystem.h"
#include "qgsrendercontext.h"
#include "qgslinestring.h"
#include "qgspolygon.h"

class QgsFeedback;
class QgsMarkerSymbol;
class QgsLineSymbol;
class QgsFillSymbol;

/**
* \ingroup core
Expand Down Expand Up @@ -112,4 +116,63 @@ class CORE_EXPORT QgsMarkerItem : public QgsAnnotationItem

};


class CORE_EXPORT QgsLineStringItem : public QgsAnnotationItem
{
public:

QgsLineStringItem( const QgsLineString &linestring, const QgsCoordinateReferenceSystem &crs );
~QgsLineStringItem() override;

QString type() const override;
void render( QgsRenderContext &context, QgsFeedback *feedback ) override;
bool writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const override;
static QgsLineStringItem *create() SIP_FACTORY;
static QgsLineStringItem *createFromElement( const QDomElement &element, const QgsReadWriteContext &context ) SIP_FACTORY;

QgsLineStringItem *clone() override SIP_FACTORY;

const QgsLineSymbol *symbol() const;
void setSymbol( QgsLineSymbol *symbol SIP_TRANSFER );

private:

QgsLineString mLineString;
std::unique_ptr< QgsLineSymbol > mSymbol;

#ifdef SIP_RUN
QgsLineStringItem( const QgsLineStringItem &other );
#endif

};


class CORE_EXPORT QgsPolygonItem : public QgsAnnotationItem
{
public:

QgsPolygonItem( const QgsPolygon &polygon, const QgsCoordinateReferenceSystem &crs );
~QgsPolygonItem() override;

QString type() const override;
void render( QgsRenderContext &context, QgsFeedback *feedback ) override;
bool writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const override;
static QgsPolygonItem *create() SIP_FACTORY;
static QgsPolygonItem *createFromElement( const QDomElement &element, const QgsReadWriteContext &context ) SIP_FACTORY;

QgsPolygonItem *clone() override SIP_FACTORY;

const QgsFillSymbol *symbol() const;
void setSymbol( QgsFillSymbol *symbol SIP_TRANSFER );

private:

QgsPolygon mPolygon;
std::unique_ptr< QgsFillSymbol > mSymbol;

#ifdef SIP_RUN
QgsPolygonItem( const QgsPolygonItem &other );
#endif

};
#endif // QGSANNOTATIONITEM_H
5 changes: 4 additions & 1 deletion src/core/annotations/qgsannotationitemregistry.cpp
Expand Up @@ -35,7 +35,10 @@ bool QgsAnnotationItemRegistry::populate()

mMetadata.insert( QStringLiteral( "marker" ), new QgsAnnotationItemMetadata( QStringLiteral( "marker" ), QObject::tr( "Marker" ), QObject::tr( "Markers" ),
QgsMarkerItem::create, QgsMarkerItem::createFromElement ) );

mMetadata.insert( QStringLiteral( "linestring" ), new QgsAnnotationItemMetadata( QStringLiteral( "linestring" ), QObject::tr( "Polyline" ), QObject::tr( "Polylines" ),
QgsLineStringItem::create, QgsLineStringItem::createFromElement ) );
mMetadata.insert( QStringLiteral( "polygon" ), new QgsAnnotationItemMetadata( QStringLiteral( "polygon" ), QObject::tr( "Polygon" ), QObject::tr( "Polygons" ),
QgsPolygonItem::create, QgsPolygonItem::createFromElement ) );
return true;
}

Expand Down

0 comments on commit fbad4e3

Please sign in to comment.