line poly items

This commit is contained in:
Nyall Dawson 2019-10-22 13:54:20 +10:00
parent c5532d0554
commit fbad4e393f
3 changed files with 285 additions and 1 deletions

View File

@ -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 );
}

View File

@ -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
@ -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

View File

@ -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;
}