00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
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;
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
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 );
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
00103 QgsRectangle viewExtent = renderContext.extent();
00104
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
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
00137 if ( !resultLabelList )
00138 {
00139 return;
00140 }
00141
00142
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
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
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
00192
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
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
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 }