QgsLabelFeature* QgsVectorLayerDiagramProvider::registerDiagram( QgsFeature& feat, QgsRenderContext &context, QgsGeometry* obstacleGeometry ) { const QgsMapSettings& mapSettings = mEngine->mapSettings(); QgsDiagramRendererV2* dr = mSettings.renderer; if ( dr ) { QList<QgsDiagramSettings> settingList = dr->diagramSettings(); if ( !settingList.isEmpty() && settingList.at( 0 ).scaleBasedVisibility ) { double minScale = settingList.at( 0 ).minScaleDenominator; if ( minScale > 0 && context.rendererScale() < minScale ) { return nullptr; } double maxScale = settingList.at( 0 ).maxScaleDenominator; if ( maxScale > 0 && context.rendererScale() > maxScale ) { return nullptr; } } } //convert geom to geos const QgsGeometry* geom = feat.constGeometry(); QScopedPointer<QgsGeometry> extentGeom( QgsGeometry::fromRect( mapSettings.visibleExtent() ) ); if ( !qgsDoubleNear( mapSettings.rotation(), 0.0 ) ) { //PAL features are prerotated, so extent also needs to be unrotated extentGeom->rotate( -mapSettings.rotation(), mapSettings.visibleExtent().center() ); } const GEOSGeometry* geos_geom = nullptr; QScopedPointer<QgsGeometry> preparedGeom; if ( QgsPalLabeling::geometryRequiresPreparation( geom, context, mSettings.ct, extentGeom.data() ) ) { preparedGeom.reset( QgsPalLabeling::prepareGeometry( geom, context, mSettings.ct, extentGeom.data() ) ); if ( !preparedGeom.data() ) return nullptr; geos_geom = preparedGeom.data()->asGeos(); } else { geos_geom = geom->asGeos(); } if ( !geos_geom ) return nullptr; // invalid geometry GEOSGeometry* geomCopy = GEOSGeom_clone_r( QgsGeometry::getGEOSHandler(), geos_geom ); const GEOSGeometry* geosObstacleGeom = nullptr; QScopedPointer<QgsGeometry> scopedObstacleGeom; if ( mSettings.obstacle && obstacleGeometry && QgsPalLabeling::geometryRequiresPreparation( obstacleGeometry, context, mSettings.ct, extentGeom.data() ) ) { scopedObstacleGeom.reset( QgsPalLabeling::prepareGeometry( obstacleGeometry, context, mSettings.ct, extentGeom.data() ) ); geosObstacleGeom = scopedObstacleGeom.data()->asGeos(); } else if ( mSettings.obstacle && obstacleGeometry ) { geosObstacleGeom = obstacleGeometry->asGeos(); } GEOSGeometry* geosObstacleGeomClone = nullptr; if ( geosObstacleGeom ) { geosObstacleGeomClone = GEOSGeom_clone_r( QgsGeometry::getGEOSHandler(), geosObstacleGeom ); } double diagramWidth = 0; double diagramHeight = 0; if ( dr ) { QSizeF diagSize = dr->sizeMapUnits( feat, context ); if ( diagSize.isValid() ) { diagramWidth = diagSize.width(); diagramHeight = diagSize.height(); } } // feature to the layer bool alwaysShow = mSettings.showAll; int ddColX = mSettings.xPosColumn; int ddColY = mSettings.yPosColumn; double ddPosX = 0.0; double ddPosY = 0.0; bool ddPos = ( ddColX >= 0 && ddColY >= 0 ); if ( ddPos ) { bool posXOk, posYOk; ddPosX = feat.attribute( ddColX ).toDouble( &posXOk ); ddPosY = feat.attribute( ddColY ).toDouble( &posYOk ); if ( !posXOk || !posYOk ) { ddPos = false; } else { const QgsCoordinateTransform* ct = mSettings.ct; if ( ct ) { double z = 0; ct->transformInPlace( ddPosX, ddPosY, z ); } //data defined diagram position is always centered ddPosX -= diagramWidth / 2.0; ddPosY -= diagramHeight / 2.0; } } QgsDiagramLabelFeature* lf = new QgsDiagramLabelFeature( feat.id(), geomCopy, QSizeF( diagramWidth, diagramHeight ) ); lf->setHasFixedPosition( ddPos ); lf->setFixedPosition( QgsPoint( ddPosX, ddPosY ) ); lf->setHasFixedAngle( true ); lf->setFixedAngle( 0 ); lf->setAlwaysShow( alwaysShow ); lf->setIsObstacle( mSettings.obstacle ); if ( geosObstacleGeomClone ) { lf->setObstacleGeometry( geosObstacleGeomClone ); } if ( dr ) { //append the diagram attributes to lbl lf->setAttributes( feat.attributes() ); } QgsPoint ptZero = mSettings.xform->toMapCoordinates( 0, 0 ); QgsPoint ptOne = mSettings.xform->toMapCoordinates( 1, 0 ); lf->setDistLabel( qAbs( ptOne.x() - ptZero.x() ) * mSettings.dist ); return lf; }
void QgsPalLabeling::registerDiagramFeature( QgsVectorLayer* layer, QgsFeature& feat, const QgsRenderContext& context ) { //get diagram layer settings, diagram renderer QHash<QgsVectorLayer*, QgsDiagramLayerSettings>::iterator layerIt = mActiveDiagramLayers.find( layer ); if ( layerIt == mActiveDiagramLayers.constEnd() ) { return; } //convert geom to geos QgsGeometry* geom = feat.geometry(); if ( layerIt.value().ct && !willUseLayer( layer ) ) // reproject the geometry if feature not already transformed for labeling { geom->transform( *( layerIt.value().ct ) ); } GEOSGeometry* geos_geom = geom->asGeos(); if ( geos_geom == 0 ) { return; // invalid geometry } //create PALGeometry with diagram = true QgsPalGeometry* lbl = new QgsPalGeometry( feat.id(), "", GEOSGeom_clone( geos_geom ) ); lbl->setIsDiagram( true ); // record the created geometry - it will be deleted at the end. layerIt.value().geometries.append( lbl ); double diagramWidth = 0; double diagramHeight = 0; QgsDiagramRendererV2* dr = layerIt.value().renderer; if ( dr ) { QSizeF diagSize = dr->sizeMapUnits( feat.attributeMap(), context ); if ( diagSize.isValid() ) { diagramWidth = diagSize.width(); diagramHeight = diagSize.height(); } //append the diagram attributes to lbl QList<int> diagramAttrib = dr->diagramAttributes(); QList<int>::const_iterator diagAttIt = diagramAttrib.constBegin(); for ( ; diagAttIt != diagramAttrib.constEnd(); ++diagAttIt ) { lbl->addDiagramAttribute( *diagAttIt, feat.attributeMap()[*diagAttIt] ); } } // register feature to the layer int ddColX = layerIt.value().xPosColumn; int ddColY = layerIt.value().yPosColumn; double ddPosX = 0.0; double ddPosY = 0.0; bool ddPos = ( ddColX >= 0 && ddColY >= 0 ); if ( ddPos ) { bool posXOk, posYOk; //data defined diagram position is always centered ddPosX = feat.attributeMap()[ddColX].toDouble( &posXOk ) - diagramWidth / 2.0; ddPosY = feat.attributeMap()[ddColY].toDouble( &posYOk ) - diagramHeight / 2.0; if ( !posXOk || !posYOk ) { ddPos = false; } else { const QgsCoordinateTransform* ct = layerIt.value().ct; if ( ct ) { double z = 0; ct->transformInPlace( ddPosX, ddPosY, z ); } } } try { if ( !layerIt.value().palLayer->registerFeature( lbl->strId(), lbl, diagramWidth, diagramHeight, "", ddPosX, ddPosY, ddPos ) ) { return; } } catch ( std::exception &e ) { Q_UNUSED( e ); QgsDebugMsg( QString( "Ignoring feature %1 due PAL exception: " ).arg( feat.id() ) + QString::fromLatin1( e.what() ) ); return; } pal::Feature* palFeat = layerIt.value().palLayer->getFeature( lbl->strId() ); QgsPoint ptZero = layerIt.value().xform->toMapCoordinates( 0, 0 ); QgsPoint ptOne = layerIt.value().xform->toMapCoordinates( 1, 0 ); palFeat->setDistLabel( qAbs( ptOne.x() - ptZero.x() ) * layerIt.value().dist ); }