Skip to content

Commit 0a6dfa1

Browse files
author
wonder
committedJul 4, 2009
Added option to engine configuration to show candidate labels for every feature (as frames).
Added a simple tool that shows candidate's cost on click (in a tooltip). git-svn-id: http://svn.osgeo.org/qgis/branches/symbology-ng-branch@11019 c8812cc2-4d05-0410-92ff-de0c093fc19c

File tree

6 files changed

+179
-16
lines changed

6 files changed

+179
-16
lines changed
 

‎src/plugins/labeling/engineconfigdialog.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ EngineConfigDialog::EngineConfigDialog(PalLabeling* lbl, QWidget* parent)
1818
spinCandPoint->setValue(candPoint);
1919
spinCandLine->setValue(candLine);
2020
spinCandPolygon->setValue(candPolygon);
21+
22+
chkShowCandidates->setChecked( mLBL->isShowingCandidates() );
2123
}
2224

2325

@@ -30,5 +32,7 @@ void EngineConfigDialog::onOK()
3032
spinCandLine->value(),
3133
spinCandPolygon->value());
3234

35+
mLBL->setShowingCandidates( chkShowCandidates->isChecked() );
36+
3337
accept();
3438
}

‎src/plugins/labeling/engineconfigdialog.ui

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
<widget class="QComboBox" name="cboSearchMethod">
2828
<item>
2929
<property name="text">
30-
<string>Chain (fastest)</string>
30+
<string>Chain (fast)</string>
3131
</property>
3232
</item>
3333
<item>
@@ -45,6 +45,11 @@
4545
<string>Popmusic Tabu Chain</string>
4646
</property>
4747
</item>
48+
<item>
49+
<property name="text">
50+
<string>FALP (fastest)</string>
51+
</property>
52+
</item>
4853
</widget>
4954
</item>
5055
</layout>
@@ -88,6 +93,9 @@
8893
<property name="minimum">
8994
<number>1</number>
9095
</property>
96+
<property name="maximum">
97+
<number>999</number>
98+
</property>
9199
</widget>
92100
</item>
93101
<item row="1" column="0">
@@ -105,6 +113,9 @@
105113
<property name="minimum">
106114
<number>1</number>
107115
</property>
116+
<property name="maximum">
117+
<number>999</number>
118+
</property>
108119
</widget>
109120
</item>
110121
<item row="2" column="0">
@@ -122,6 +133,9 @@
122133
<property name="minimum">
123134
<number>1</number>
124135
</property>
136+
<property name="maximum">
137+
<number>999</number>
138+
</property>
125139
</widget>
126140
</item>
127141
</layout>
@@ -158,6 +172,13 @@
158172
</property>
159173
</spacer>
160174
</item>
175+
<item>
176+
<widget class="QCheckBox" name="chkShowCandidates">
177+
<property name="text">
178+
<string>Show label candidates (for debugging)</string>
179+
</property>
180+
</widget>
181+
</item>
161182
<item>
162183
<widget class="QDialogButtonBox" name="buttonBox">
163184
<property name="orientation">
@@ -170,6 +191,14 @@
170191
</item>
171192
</layout>
172193
</widget>
194+
<tabstops>
195+
<tabstop>cboSearchMethod</tabstop>
196+
<tabstop>spinCandPoint</tabstop>
197+
<tabstop>spinCandLine</tabstop>
198+
<tabstop>spinCandPolygon</tabstop>
199+
<tabstop>chkShowCandidates</tabstop>
200+
<tabstop>buttonBox</tabstop>
201+
</tabstops>
173202
<resources/>
174203
<connections>
175204
<connection>

‎src/plugins/labeling/labeling.cpp

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,46 @@ Labeling::~Labeling()
6565
{
6666
}
6767

68+
/////////
69+
70+
#include <qgsmaptool.h>
71+
#include <QMouseEvent>
72+
#include <QToolTip>
73+
74+
class LabelingTool : public QgsMapTool
75+
{
76+
public:
77+
LabelingTool(PalLabeling* lbl, QgsMapCanvas* canvas) : QgsMapTool(canvas), mLBL(lbl) {}
78+
79+
virtual void canvasPressEvent( QMouseEvent * e )
80+
{
81+
const QList<LabelCandidate>& cand = mLBL->candidates();
82+
QPointF pt = e->posF();
83+
for (int i = 0; i < cand.count(); i++)
84+
{
85+
const LabelCandidate& c = cand[i];
86+
if (c.rect.contains(pt))
87+
{
88+
QToolTip::showText( mCanvas->mapToGlobal(e->pos()), QString::number(c.cost), mCanvas);
89+
break;
90+
}
91+
}
92+
}
93+
94+
protected:
95+
PalLabeling* mLBL;
96+
};
97+
98+
///////////
99+
100+
68101
/*
69102
* Initialize the GUI interface for the plugin - this is only called once when the plugin is
70103
* added to the plugin registry in the QGIS application.
71104
*/
72105
void Labeling::initGui()
73106
{
74-
mLBL = new PalLabeling(mQGisIface->mapCanvas());
107+
mLBL = new PalLabeling(mQGisIface->mapCanvas()->mapRenderer());
75108

76109
// Create the action for tool
77110
mQActionPointer = new QAction( QIcon( ":/labeling/labeling.png" ), tr( "Labeling" ), this );
@@ -83,13 +116,19 @@ void Labeling::initGui()
83116
mQGisIface->addToolBarIcon( mQActionPointer );
84117
mQGisIface->addPluginToMenu( tr( "&Labeling" ), mQActionPointer );
85118

119+
mActionTool = new QAction( "Ltool", this );
120+
mQGisIface->addToolBarIcon( mActionTool );
121+
connect( mActionTool, SIGNAL( triggered() ), this, SLOT( setTool() ) );
122+
123+
mTool = new LabelingTool(mLBL, mQGisIface->mapCanvas());
124+
86125
connect( mQGisIface->mapCanvas(), SIGNAL( renderComplete( QPainter * ) ), this, SLOT( doLabeling( QPainter * ) ) );
87126

88127
}
89128

90129
void Labeling::doLabeling( QPainter * painter )
91130
{
92-
mLBL->doLabeling(painter);
131+
mLBL->doLabeling(painter, mQGisIface->mapCanvas()->extent());
93132
}
94133

95134
// Slot called when the menu item is triggered
@@ -119,14 +158,26 @@ void Labeling::run()
119158
}
120159
}
121160

161+
162+
void Labeling::setTool()
163+
{
164+
mQGisIface->mapCanvas()->setMapTool(mTool);
165+
}
166+
122167
// Unload the plugin by cleaning up the GUI
123168
void Labeling::unload()
124169
{
170+
mQGisIface->mapCanvas()->unsetMapTool(mTool);
171+
delete mTool;
172+
125173
// remove the GUI
126174
mQGisIface->removePluginMenu( "&Labeling", mQActionPointer );
127175
mQGisIface->removeToolBarIcon( mQActionPointer );
128176
delete mQActionPointer;
129177

178+
mQGisIface->removeToolBarIcon( mActionTool );
179+
delete mActionTool;
180+
130181
delete mLBL;
131182
}
132183

‎src/plugins/labeling/labeling.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class QToolBar;
3232
class QgisInterface;
3333

3434
class PalLabeling;
35+
class LabelingTool;
3536

3637
class Labeling: public QObject, public QgisPlugin
3738
{
@@ -58,14 +59,20 @@ class Labeling: public QObject, public QgisPlugin
5859
//! hook to renderComplete signal
5960
void doLabeling(QPainter* painter);
6061

62+
//! start labeling map tool
63+
void setTool();
64+
6165
private:
6266

6367
//! Pointer to the QGIS interface object
6468
QgisInterface *mQGisIface;
6569
//! Pointer to the qaction for this plugin
6670
QAction * mQActionPointer;
71+
QAction * mActionTool;
6772

6873
PalLabeling* mLBL;
74+
75+
LabelingTool* mTool;
6976
};
7077

7178
#endif //Labeling_H

‎src/plugins/labeling/pallabeling.cpp

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#include <pal/layer.h>
88
#include <pal/palgeometry.h>
99
#include <pal/palexception.h>
10+
#include <pal/problem.h>
11+
#include <pal/labelposition.h>
1012

1113
#include <geos_c.h>
1214

@@ -15,12 +17,14 @@
1517
#include <QByteArray>
1618
#include <QString>
1719
#include <QFontMetrics>
20+
#include <QTime>
21+
#include <QPainter>
1822

1923
#include <qgsvectorlayer.h>
2024
#include <qgsmaplayerregistry.h>
2125
#include <qgsvectordataprovider.h>
2226
#include <qgsgeometry.h>
23-
#include <qgsmapcanvas.h>
27+
#include <qgsmaprenderer.h>
2428

2529
using namespace pal;
2630

@@ -105,8 +109,8 @@ void LayerSettings::registerFeature(QgsFeature& f)
105109

106110
// -------------
107111

108-
PalLabeling::PalLabeling(QgsMapCanvas* mapCanvas)
109-
: mMapCanvas(mapCanvas), mPal(NULL)
112+
PalLabeling::PalLabeling(QgsMapRenderer* mapRenderer)
113+
: mMapRenderer(mapRenderer), mPal(NULL)
110114
{
111115

112116
// find out engine defaults
@@ -121,8 +125,11 @@ PalLabeling::PalLabeling(QgsMapCanvas* mapCanvas)
121125
case POPMUSIC_TABU: mSearch = Popmusic_Tabu; break;
122126
case POPMUSIC_CHAIN: mSearch = Popmusic_Chain; break;
123127
case POPMUSIC_TABU_CHAIN: mSearch = Popmusic_Tabu_Chain; break;
128+
case FALP: mSearch = Falp; break;
124129
}
125130

131+
mShowingCandidates = FALSE;
132+
126133
initPal();
127134
}
128135

@@ -217,7 +224,7 @@ int PalLabeling::prepareLayerHook(void* context, void* layerContext, int& attrIn
217224
lyr->fieldIndex = fldIndex;
218225
lyr->fontMetrics = new QFontMetrics(lyr->textFont);
219226
lyr->fontBaseline = lyr->fontMetrics->boundingRect("X").bottom(); // dummy text to find out how many pixels of the text are below the baseline
220-
lyr->xform = thisClass->mMapCanvas->mapRenderer()->coordinateTransform();
227+
lyr->xform = thisClass->mMapRenderer->coordinateTransform();
221228
lyr->ptZero = lyr->xform->toMapCoordinates( 0,0 );
222229

223230
return 1; // init successful
@@ -245,6 +252,7 @@ void PalLabeling::initPal()
245252
case Popmusic_Tabu: s = POPMUSIC_TABU; break;
246253
case Popmusic_Chain: s = POPMUSIC_CHAIN; break;
247254
case Popmusic_Tabu_Chain: s = POPMUSIC_TABU_CHAIN; break;
255+
case Falp: s = FALP; break;
248256
}
249257
mPal->setSearch(s);
250258
//mPal->setSearch(FALP);
@@ -257,7 +265,7 @@ void PalLabeling::initPal()
257265

258266

259267

260-
void PalLabeling::doLabeling(QPainter* painter)
268+
void PalLabeling::doLabeling(QPainter* painter, QgsRectangle extent)
261269
{
262270

263271
QTime t;
@@ -274,25 +282,70 @@ void PalLabeling::doLabeling(QPainter* painter)
274282

275283
// do the labeling itself
276284
double scale = 1; // scale denominator
277-
QgsRectangle r = mMapCanvas->extent();
285+
QgsRectangle r = extent;
278286
double bbox[] = { r.xMinimum(), r.yMinimum(), r.xMaximum(), r.yMaximum() };
279287

280288
std::list<Label*>* labels;
289+
pal::Problem* problem;
281290
try
282291
{
283-
labels = mPal->labeller(scale, bbox, NULL, false);
292+
//labels = mPal->labeller(scale, bbox, NULL, false);
293+
problem = mPal->extractProblem(scale, bbox);
294+
if ( problem )
295+
{
296+
// TODO: other methods
297+
problem->chain_search();
298+
labels = problem->getSolution(false);
299+
}
300+
else
301+
labels = new std::list<Label*>();
284302
}
285303
catch ( std::exception& e )
286304
{
287305
std::cerr << "PAL EXCEPTION :-( " << e.what() << std::endl;
288306
return;
289307
}
290308

309+
const QgsMapToPixel* xform = mMapRenderer->coordinateTransform();
310+
311+
// draw rectangles with all candidates
312+
// this is done before actual solution of the problem
313+
// before number of candidates gets reduced
314+
mCandidates.clear();
315+
if (mShowingCandidates && problem)
316+
{
317+
painter->setPen(QColor(0,0,0,64));
318+
painter->setBrush(Qt::NoBrush);
319+
for (int i = 0; i < problem->getNumFeatures(); i++)
320+
{
321+
for (int j = 0; j < problem->getFeatureCandidateCount(i); j++)
322+
{
323+
pal::LabelPosition* lp = problem->getFeatureCandidate(i, j);
324+
325+
QgsPoint outPt = xform->transform(lp->getX(), lp->getY());
326+
QgsPoint outPt2 = xform->transform(lp->getX()+lp->getWidth(), lp->getY()+lp->getHeight());
327+
328+
painter->save();
329+
painter->translate( QPointF(outPt.x(), outPt.y()) );
330+
painter->rotate(-lp->getAlpha() * 180 / M_PI );
331+
QRectF rect(0,0, outPt2.x()-outPt.x(), outPt2.y()-outPt.y());
332+
painter->drawRect(rect);
333+
painter->restore();
334+
335+
// save the rect
336+
rect.moveTo(outPt.x(),outPt.y());
337+
mCandidates.append( LabelCandidate(rect, lp->getCost() * 1000) );
338+
}
339+
}
340+
}
341+
342+
// find the solution
343+
labels = mPal->solveProblem( problem );
344+
291345
std::cout << "LABELING work: " << t.elapsed() << "ms ... labels# " << labels->size() << std::endl;
292346
t.restart();
293347

294348
// draw the labels
295-
const QgsMapToPixel* xform = mMapCanvas->mapRenderer()->coordinateTransform();
296349
std::list<Label*>::iterator it = labels->begin();
297350
for ( ; it != labels->end(); ++it)
298351
{
@@ -317,6 +370,7 @@ void PalLabeling::doLabeling(QPainter* painter)
317370

318371
std::cout << "LABELING draw: " << t.elapsed() << "ms" << std::endl;
319372

373+
delete problem;
320374
delete labels;
321375

322376
// delete all allocated geometries for features

‎src/plugins/labeling/pallabeling.h

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22
#define PALLABELING_H
33

44
class QPainter;
5-
class QgsMapCanvas;
5+
class QgsMapRenderer;
6+
class QgsRectangle;
67

78
#include <QString>
89
#include <QFont>
910
#include <QColor>
1011
#include <QList>
12+
#include <QRectF>
1113

1214
namespace pal
1315
{
@@ -62,13 +64,22 @@ class LayerSettings
6264
QList<MyLabel*> geometries;
6365
};
6466

67+
class LabelCandidate
68+
{
69+
public:
70+
LabelCandidate(QRectF r, double c): rect(r), cost(c) {}
71+
72+
QRectF rect;
73+
double cost;
74+
};
75+
6576
class PalLabeling
6677
{
6778
public:
68-
PalLabeling(QgsMapCanvas* mapCanvas);
79+
PalLabeling(QgsMapRenderer* renderer);
6980
~PalLabeling();
7081

71-
void doLabeling(QPainter* painter);
82+
void doLabeling(QPainter* painter, QgsRectangle extent);
7283

7384
void addLayer(LayerSettings layerSettings);
7485

@@ -79,11 +90,14 @@ class PalLabeling
7990
void numCandidatePositions(int& candPoint, int& candLine, int& candPolygon);
8091
void setNumCandidatePositions(int candPoint, int candLine, int candPolygon);
8192

82-
enum Search { Chain, Popmusic_Tabu, Popmusic_Chain, Popmusic_Tabu_Chain };
93+
enum Search { Chain, Popmusic_Tabu, Popmusic_Chain, Popmusic_Tabu_Chain, Falp };
8394

8495
void setSearchMethod(Search s);
8596
Search searchMethod() const;
8697

98+
bool isShowingCandidates() const { return mShowingCandidates; }
99+
void setShowingCandidates(bool showing) { mShowingCandidates = showing; }
100+
const QList<LabelCandidate>& candidates() { return mCandidates; }
87101

88102
//! hook called when drawing layer before issuing select()
89103
static int prepareLayerHook(void* context, void* layerContext, int& attrIndex);
@@ -96,11 +110,15 @@ class PalLabeling
96110

97111
protected:
98112
QList<LayerSettings> mLayers;
99-
QgsMapCanvas* mMapCanvas;
113+
QgsMapRenderer* mMapRenderer;
100114
int mCandPoint, mCandLine, mCandPolygon;
101115
Search mSearch;
102116

103117
pal::Pal* mPal;
118+
119+
// list of candidates from last labeling
120+
QList<LabelCandidate> mCandidates;
121+
bool mShowingCandidates;
104122
};
105123

106124
#endif // PALLABELING_H

0 commit comments

Comments
 (0)
Please sign in to comment.