Quantum GIS API Documentation  1.7.5-Wroclaw
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
qgspalobjectpositionmanager.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgspalobjectpositionmanager.cpp - description
3  ---------------------------------
4  begin : October 2008
5  copyright : (C) 2008 by Marco Hugentobler
6  email : marco dot hugentobler at karto dot baug dot ethz dot ch
7 ***************************************************************************/
8 
9 /***************************************************************************
10  * *
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. *
15  * *
16  ***************************************************************************/
17 
19 #include "qgsgeometry.h"
20 #include "qgspalgeometry.h"
21 #include "qgsoverlayobject.h"
22 #include "qgsrendercontext.h"
23 #include "qgsvectorlayer.h"
24 #include "qgsvectoroverlay.h"
25 #include "pal.h"
26 #include "labelposition.h"
27 #include "feature.h"
28 #include "layer.h"
29 
31 {
32 
33 }
34 
36 {
38 }
39 
40 void QgsPALObjectPositionManager::addLayer( QgsVectorLayer* vl, QList<QgsVectorOverlay*>& overlays )
41 {
42  if ( overlays.size() < 1 )
43  {
44  return;
45  }
46 
47  //set arrangement based on vector type
48  pal::Arrangement labelArrangement;
49  switch ( vl->geometryType() )
50  {
51  case QGis::Point:
52  labelArrangement = pal::P_POINT;
53  break;
54  case QGis::Line:
55  labelArrangement = pal::P_LINE;
56  break;
57  case QGis::Polygon:
58  labelArrangement = pal::P_HORIZ;
59  break;
60  default:
61  return; //error
62  }
63 
64  pal::Layer* positionLayer = mPositionEngine.addLayer( QString::number( mNumberOfLayers ).toLocal8Bit().data(), -1, -1, labelArrangement, pal::PIXEL, 0.5, true, true, true );
66 
67  if ( !positionLayer )
68  {
69  return;
70  }
71 
72  //register the labeling objects in the layer
73  int objectNr = 0;
74  QList<QgsVectorOverlay*>::const_iterator overlayIt = overlays.begin();
75  for ( ; overlayIt != overlays.end(); ++overlayIt )
76  {
77  if ( !( *overlayIt ) )
78  {
79  continue;
80  }
81 
82  QMap<int, QgsOverlayObject*>* positionObjects = ( *overlayIt )->overlayObjects();
83  if ( !positionObjects )
84  {
85  continue;
86  }
87 
88  QMap<int, QgsOverlayObject*>::const_iterator objectIt = positionObjects->begin();
89  for ( ; objectIt != positionObjects->end(); ++objectIt )
90  {
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() );
95  ++objectNr;
96  }
97  }
98 }
99 
101 {
102  //trigger label placement
103  QgsRectangle viewExtent = renderContext.extent();
104  //PAL needs projected view extent
105  if ( renderContext.coordinateTransform() )
106  {
107  viewExtent = renderContext.coordinateTransform()->transformBoundingBox( viewExtent );
108  }
109  double bbox[4]; bbox[0] = viewExtent.xMinimum(); bbox[1] = viewExtent.yMinimum(); bbox[2] = viewExtent.xMaximum(); bbox[3] = viewExtent.yMaximum();
110 
111 
112  //set map units
113  pal::Units mapUnits;
114  switch ( unitType )
115  {
116  case QGis::Meters:
117  mapUnits = pal::METER;
118  break;
119 
120  case QGis::Feet:
121  mapUnits = pal::FOOT;
122  break;
123 
124  case QGis::Degrees:
125  mapUnits = pal::DEGREE;
126  break;
127  default:
128  return;
129  }
130 
131  mPositionEngine.setMapUnit( mapUnits );
132  mPositionEngine.setDpi( renderContext.scaleFactor() * 25.4 );
133 
134  std::list<pal::LabelPosition*>* resultLabelList = mPositionEngine.labeller( renderContext.rendererScale(), bbox, NULL, false );
135 
136  //and read the positions back to the overlay objects
137  if ( !resultLabelList )
138  {
139  return;
140  }
141 
142  //pal geometry that the current label object refers to
143  QgsPALGeometry* referredGeometry = 0;
144  QgsOverlayObject* referredOverlayObject = 0;
145  pal::FeaturePart* referredPart = 0;
146 
147  std::list<pal::LabelPosition*>::iterator labelIt = resultLabelList->begin();
148  for ( ; labelIt != resultLabelList->end(); ++labelIt )
149  {
150  if ( !*labelIt )
151  {
152  continue;
153  }
154 
155  referredPart = ( *labelIt )->getFeaturePart();
156  if ( !referredPart )
157  {
158  continue;
159  }
160  referredGeometry = dynamic_cast<QgsPALGeometry*>( referredPart->getUserGeometry() );
161  if ( !referredGeometry )
162  {
163  continue;
164  }
165  referredOverlayObject = referredGeometry->overlayObjectPtr();
166  if ( !referredOverlayObject )
167  {
168  continue;
169  }
170 
171  pal::LabelPosition* lp = *labelIt;
172 
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 ) );
177  }
178 
179  //release memory for QgsPALGeometries
181 }
182 
184 {
185  std::list<pal::Layer*>* layerList = mPositionEngine.getLayers();
186  if ( !layerList )
187  {
188  return;
189  }
190 
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 )
196  {
197  layersToRemove.push_back( *layerIt );
198  }
199 
200  QList<pal::Layer*>::iterator removeIt = layersToRemove.begin();
201  for ( ; removeIt != layersToRemove.end(); ++removeIt )
202  {
203  mPositionEngine.removeLayer( *removeIt );
204  }
205 }
206 //Chain, Popmusic tabu chain, Popmusic tabu, Popmusic chain
207 void QgsPALObjectPositionManager::setPlacementAlgorithm( const QString& algorithmName )
208 {
209  if ( algorithmName == "Popmusic tabu chain" )
210  {
211  mPositionEngine.setSearch( pal::POPMUSIC_TABU_CHAIN );
212  }
213  else if ( algorithmName == "Popmusic tabu" )
214  {
215  mPositionEngine.setSearch( pal::POPMUSIC_TABU );
216  }
217  else if ( algorithmName == "Popmusic chain" )
218  {
219  mPositionEngine.setSearch( pal::POPMUSIC_CHAIN );
220  }
221  else //default is "Chain"
222  {
223  mPositionEngine.setSearch( pal::CHAIN );
224  }
225 }
226 
228 {
229  QList<QgsPALGeometry*>::iterator geomIt = mPALGeometries.begin();
230  for ( ; geomIt != mPALGeometries.end(); ++geomIt )
231  {
232  delete( *geomIt );
233  }
234  mPALGeometries.clear();
235 }