Quantum GIS API Documentation  1.7.4
src/core/qgspalobjectpositionmanager.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                         qgspalobjectpositionmanager.cpp  -  description
00003                         ---------------------------------
00004    begin                : October 2008
00005    copyright            : (C) 2008 by Marco Hugentobler
00006    email                : marco dot hugentobler at karto dot baug dot ethz dot ch
00007 ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 #include "qgspalobjectpositionmanager.h"
00019 #include "qgsgeometry.h"
00020 #include "qgspalgeometry.h"
00021 #include "qgsoverlayobject.h"
00022 #include "qgsrendercontext.h"
00023 #include "qgsvectorlayer.h"
00024 #include "qgsvectoroverlay.h"
00025 #include "pal.h"
00026 #include "labelposition.h"
00027 #include "feature.h"
00028 #include "layer.h"
00029 
00030 QgsPALObjectPositionManager::QgsPALObjectPositionManager(): mNumberOfLayers( 0 )
00031 {
00032 
00033 }
00034 
00035 QgsPALObjectPositionManager::~QgsPALObjectPositionManager()
00036 {
00037   deletePALGeometries();
00038 }
00039 
00040 void QgsPALObjectPositionManager::addLayer( QgsVectorLayer* vl, QList<QgsVectorOverlay*>& overlays )
00041 {
00042   if ( overlays.size() < 1 )
00043   {
00044     return;
00045   }
00046 
00047   //set arrangement based on vector type
00048   pal::Arrangement labelArrangement;
00049   switch ( vl->geometryType() )
00050   {
00051     case QGis::Point:
00052       labelArrangement = pal::P_POINT;
00053       break;
00054     case QGis::Line:
00055       labelArrangement = pal::P_LINE;
00056       break;
00057     case QGis::Polygon:
00058       labelArrangement = pal::P_HORIZ;
00059       break;
00060     default:
00061       return; //error
00062   }
00063 
00064   pal::Layer* positionLayer = mPositionEngine.addLayer( QString::number( mNumberOfLayers ).toLocal8Bit().data(), -1, -1, labelArrangement, pal::PIXEL, 0.5, true, true, true );
00065   ++mNumberOfLayers;
00066 
00067   if ( !positionLayer )
00068   {
00069     return;
00070   }
00071 
00072   //register the labeling objects in the layer
00073   int objectNr = 0;
00074   QList<QgsVectorOverlay*>::const_iterator overlayIt = overlays.begin();
00075   for ( ; overlayIt != overlays.end(); ++overlayIt )
00076   {
00077     if ( !( *overlayIt ) )
00078     {
00079       continue;
00080     }
00081 
00082     QMap<int, QgsOverlayObject*>* positionObjects = ( *overlayIt )->overlayObjects();
00083     if ( !positionObjects )
00084     {
00085       continue;
00086     }
00087 
00088     QMap<int, QgsOverlayObject*>::const_iterator objectIt = positionObjects->begin();
00089     for ( ; objectIt != positionObjects->end(); ++objectIt )
00090     {
00091       QgsPALGeometry* palGeom = new QgsPALGeometry( objectIt.value() );
00092       mPALGeometries.push_back( palGeom ); //insert object into list to delete memory later
00093       char* featureLabel = QString::number( objectNr ).toAscii().data();
00094       positionLayer->registerFeature( featureLabel, palGeom, objectIt.value()->width(), objectIt.value()->height() );
00095       ++objectNr;
00096     }
00097   }
00098 }
00099 
00100 void QgsPALObjectPositionManager::findObjectPositions( const QgsRenderContext& renderContext, QGis::UnitType unitType )
00101 {
00102   //trigger label placement
00103   QgsRectangle viewExtent = renderContext.extent();
00104   //PAL needs projected view extent
00105   if ( renderContext.coordinateTransform() )
00106   {
00107     viewExtent = renderContext.coordinateTransform()->transformBoundingBox( viewExtent );
00108   }
00109   double bbox[4]; bbox[0] = viewExtent.xMinimum(); bbox[1] = viewExtent.yMinimum(); bbox[2] = viewExtent.xMaximum(); bbox[3] = viewExtent.yMaximum();
00110 
00111 
00112   //set map units
00113   pal::Units mapUnits;
00114   switch ( unitType )
00115   {
00116     case QGis::Meters:
00117       mapUnits = pal::METER;
00118       break;
00119 
00120     case QGis::Feet:
00121       mapUnits = pal::FOOT;
00122       break;
00123 
00124     case QGis::Degrees:
00125       mapUnits = pal::DEGREE;
00126       break;
00127     default:
00128       return;
00129   }
00130 
00131   mPositionEngine.setMapUnit( mapUnits );
00132   mPositionEngine.setDpi( renderContext.scaleFactor() * 25.4 );
00133 
00134   std::list<pal::LabelPosition*>* resultLabelList = mPositionEngine.labeller( renderContext.rendererScale(), bbox, NULL, false );
00135 
00136   //and read the positions back to the overlay objects
00137   if ( !resultLabelList )
00138   {
00139     return;
00140   }
00141 
00142   //pal geometry that the current label object refers to
00143   QgsPALGeometry* referredGeometry = 0;
00144   QgsOverlayObject* referredOverlayObject = 0;
00145   pal::FeaturePart* referredPart = 0;
00146 
00147   std::list<pal::LabelPosition*>::iterator labelIt = resultLabelList->begin();
00148   for ( ; labelIt != resultLabelList->end(); ++labelIt )
00149   {
00150     if ( !*labelIt )
00151     {
00152       continue;
00153     }
00154 
00155     referredPart = ( *labelIt )->getFeaturePart();
00156     if ( !referredPart )
00157     {
00158       continue;
00159     }
00160     referredGeometry = dynamic_cast<QgsPALGeometry*>( referredPart->getUserGeometry() );
00161     if ( !referredGeometry )
00162     {
00163       continue;
00164     }
00165     referredOverlayObject = referredGeometry->overlayObjectPtr();
00166     if ( !referredOverlayObject )
00167     {
00168       continue;
00169     }
00170 
00171     pal::LabelPosition* lp = *labelIt;
00172 
00173     //QGIS takes the coordinates of the middle points
00174     double x = ( lp->getX( 0 ) + lp->getX( 1 ) + lp->getX( 2 ) + lp->getX( 3 ) ) / 4;
00175     double y = ( lp->getY( 0 ) + lp->getY( 1 ) + lp->getY( 2 ) + lp->getY( 3 ) ) / 4;
00176     referredOverlayObject->addPosition( QgsPoint( x, y ) );
00177   }
00178 
00179   //release memory for QgsPALGeometries
00180   deletePALGeometries();
00181 }
00182 
00183 void QgsPALObjectPositionManager::removeLayers()
00184 {
00185   std::list<pal::Layer*>* layerList = mPositionEngine.getLayers();
00186   if ( !layerList )
00187   {
00188     return;
00189   }
00190 
00191   //Iterators get invalid if elements are deleted in a std::list
00192   //Therefore we have to get the layer pointers in a first step and remove them in a second
00193   QList<pal::Layer*> layersToRemove;
00194   std::list<pal::Layer*>::iterator layerIt = layerList->begin();
00195   for ( ; layerIt != layerList->end(); ++layerIt )
00196   {
00197     layersToRemove.push_back( *layerIt );
00198   }
00199 
00200   QList<pal::Layer*>::iterator removeIt = layersToRemove.begin();
00201   for ( ; removeIt != layersToRemove.end(); ++removeIt )
00202   {
00203     mPositionEngine.removeLayer( *removeIt );
00204   }
00205 }
00206 //Chain, Popmusic tabu chain, Popmusic tabu, Popmusic chain
00207 void QgsPALObjectPositionManager::setPlacementAlgorithm( const QString& algorithmName )
00208 {
00209   if ( algorithmName == "Popmusic tabu chain" )
00210   {
00211     mPositionEngine.setSearch( pal::POPMUSIC_TABU_CHAIN );
00212   }
00213   else if ( algorithmName == "Popmusic tabu" )
00214   {
00215     mPositionEngine.setSearch( pal::POPMUSIC_TABU );
00216   }
00217   else if ( algorithmName == "Popmusic chain" )
00218   {
00219     mPositionEngine.setSearch( pal::POPMUSIC_CHAIN );
00220   }
00221   else //default is "Chain"
00222   {
00223     mPositionEngine.setSearch( pal::CHAIN );
00224   }
00225 }
00226 
00227 void QgsPALObjectPositionManager::deletePALGeometries()
00228 {
00229   QList<QgsPALGeometry*>::iterator geomIt = mPALGeometries.begin();
00230   for ( ; geomIt != mPALGeometries.end(); ++geomIt )
00231   {
00232     delete( *geomIt );
00233   }
00234   mPALGeometries.clear();
00235 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines