1
/***************************************************************************
2
qgspalobjectpositionmanager.cpp - description
3
---------------------------------
5
copyright : (C) 2008 by Marco Hugentobler
6
email : marco dot hugentobler at karto dot baug dot ethz dot ch
7
***************************************************************************/
9
/***************************************************************************
11
* This program is free software; you can redistribute it and/or modify *
12
* it under the terms of the GNU General Public License as published by *
13
* the Free Software Foundation; either version 2 of the License, or *
14
* (at your option) any later version. *
16
***************************************************************************/
18
#include "qgspalobjectpositionmanager.h"
19
#include "qgsgeometry.h"
20
#include "qgspalgeometry.h"
21
#include "qgsoverlayobject.h"
22
#include "qgsrendercontext.h"
23
#include "qgsvectorlayer.h"
24
#include "qgsvectoroverlay.h"
26
#include "labelposition.h"
30
QgsPALObjectPositionManager::QgsPALObjectPositionManager(): mNumberOfLayers( 0 )
35
QgsPALObjectPositionManager::~QgsPALObjectPositionManager()
37
deletePALGeometries();
40
void QgsPALObjectPositionManager::addLayer( QgsVectorLayer* vl, QList<QgsVectorOverlay*>& overlays )
42
if ( overlays.size() < 1 )
47
//set arrangement based on vector type
48
pal::Arrangement labelArrangement;
49
switch ( vl->geometryType() )
52
labelArrangement = pal::P_POINT;
55
labelArrangement = pal::P_LINE;
58
labelArrangement = pal::P_HORIZ;
64
pal::Layer* positionLayer = mPositionEngine.addLayer( QString::number( mNumberOfLayers ).toLocal8Bit().data(), -1, -1, labelArrangement, pal::PIXEL, 0.5, true, true, true );
72
//register the labeling objects in the layer
74
QList<QgsVectorOverlay*>::const_iterator overlayIt = overlays.begin();
75
for ( ; overlayIt != overlays.end(); ++overlayIt )
77
if ( !( *overlayIt ) )
82
QMap<int, QgsOverlayObject*>* positionObjects = ( *overlayIt )->overlayObjects();
83
if ( !positionObjects )
88
QMap<int, QgsOverlayObject*>::const_iterator objectIt = positionObjects->begin();
89
for ( ; objectIt != positionObjects->end(); ++objectIt )
91
QgsPALGeometry* palGeom = new QgsPALGeometry( objectIt.value() );
92
mPALGeometries.push_back( palGeom ); //insert object into list to delete memory later
93
char* featureLabel = QString::number( objectNr ).toAscii().data();
94
positionLayer->registerFeature( featureLabel, palGeom, objectIt.value()->width(), objectIt.value()->height() );
100
void QgsPALObjectPositionManager::findObjectPositions( const QgsRenderContext& renderContext, QGis::UnitType unitType )
102
//trigger label placement
103
QgsRectangle viewExtent = renderContext.extent();
104
//PAL needs projected view extent
105
if ( renderContext.coordinateTransform() )
107
viewExtent = renderContext.coordinateTransform()->transformBoundingBox( viewExtent );
109
double bbox[4]; bbox[0] = viewExtent.xMinimum(); bbox[1] = viewExtent.yMinimum(); bbox[2] = viewExtent.xMaximum(); bbox[3] = viewExtent.yMaximum();
117
mapUnits = pal::METER;
121
mapUnits = pal::FOOT;
125
mapUnits = pal::DEGREE;
131
mPositionEngine.setMapUnit( mapUnits );
132
mPositionEngine.setDpi( renderContext.scaleFactor() * 25.4 );
134
std::list<pal::LabelPosition*>* resultLabelList = mPositionEngine.labeller( renderContext.rendererScale(), bbox, NULL, false );
136
//and read the positions back to the overlay objects
137
if ( !resultLabelList )
142
//pal geometry that the current label object refers to
143
QgsPALGeometry* referredGeometry = 0;
144
QgsOverlayObject* referredOverlayObject = 0;
145
pal::FeaturePart* referredPart = 0;
147
std::list<pal::LabelPosition*>::iterator labelIt = resultLabelList->begin();
148
for ( ; labelIt != resultLabelList->end(); ++labelIt )
155
referredPart = ( *labelIt )->getFeaturePart();
160
referredGeometry = dynamic_cast<QgsPALGeometry*>( referredPart->getUserGeometry() );
161
if ( !referredGeometry )
165
referredOverlayObject = referredGeometry->overlayObjectPtr();
166
if ( !referredOverlayObject )
171
pal::LabelPosition* lp = *labelIt;
173
//QGIS takes the coordinates of the middle points
174
double x = ( lp->getX( 0 ) + lp->getX( 1 ) + lp->getX( 2 ) + lp->getX( 3 ) ) / 4;
175
double y = ( lp->getY( 0 ) + lp->getY( 1 ) + lp->getY( 2 ) + lp->getY( 3 ) ) / 4;
176
referredOverlayObject->addPosition( QgsPoint( x, y ) );
179
//release memory for QgsPALGeometries
180
deletePALGeometries();
183
void QgsPALObjectPositionManager::removeLayers()
185
std::list<pal::Layer*>* layerList = mPositionEngine.getLayers();
191
//Iterators get invalid if elements are deleted in a std::list
192
//Therefore we have to get the layer pointers in a first step and remove them in a second
193
QList<pal::Layer*> layersToRemove;
194
std::list<pal::Layer*>::iterator layerIt = layerList->begin();
195
for ( ; layerIt != layerList->end(); ++layerIt )
197
layersToRemove.push_back( *layerIt );
200
QList<pal::Layer*>::iterator removeIt = layersToRemove.begin();
201
for ( ; removeIt != layersToRemove.end(); ++removeIt )
203
mPositionEngine.removeLayer( *removeIt );
206
//Chain, Popmusic tabu chain, Popmusic tabu, Popmusic chain
207
void QgsPALObjectPositionManager::setPlacementAlgorithm( const QString& algorithmName )
209
if ( algorithmName == "Popmusic tabu chain" )
211
mPositionEngine.setSearch( pal::POPMUSIC_TABU_CHAIN );
213
else if ( algorithmName == "Popmusic tabu" )
215
mPositionEngine.setSearch( pal::POPMUSIC_TABU );
217
else if ( algorithmName == "Popmusic chain" )
219
mPositionEngine.setSearch( pal::POPMUSIC_CHAIN );
221
else //default is "Chain"
223
mPositionEngine.setSearch( pal::CHAIN );
227
void QgsPALObjectPositionManager::deletePALGeometries()
229
QList<QgsPALGeometry*>::iterator geomIt = mPALGeometries.begin();
230
for ( ; geomIt != mPALGeometries.end(); ++geomIt )
234
mPALGeometries.clear();