[QGIS Commit] r11019 -
branches/symbology-ng-branch/src/plugins/labeling
svn_qgis at osgeo.org
svn_qgis at osgeo.org
Sat Jul 4 09:35:37 EDT 2009
Author: wonder
Date: 2009-07-04 09:35:36 -0400 (Sat, 04 Jul 2009)
New Revision: 11019
Modified:
branches/symbology-ng-branch/src/plugins/labeling/engineconfigdialog.cpp
branches/symbology-ng-branch/src/plugins/labeling/engineconfigdialog.ui
branches/symbology-ng-branch/src/plugins/labeling/labeling.cpp
branches/symbology-ng-branch/src/plugins/labeling/labeling.h
branches/symbology-ng-branch/src/plugins/labeling/pallabeling.cpp
branches/symbology-ng-branch/src/plugins/labeling/pallabeling.h
Log:
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).
Modified: branches/symbology-ng-branch/src/plugins/labeling/engineconfigdialog.cpp
===================================================================
--- branches/symbology-ng-branch/src/plugins/labeling/engineconfigdialog.cpp 2009-07-04 13:25:43 UTC (rev 11018)
+++ branches/symbology-ng-branch/src/plugins/labeling/engineconfigdialog.cpp 2009-07-04 13:35:36 UTC (rev 11019)
@@ -18,6 +18,8 @@
spinCandPoint->setValue(candPoint);
spinCandLine->setValue(candLine);
spinCandPolygon->setValue(candPolygon);
+
+ chkShowCandidates->setChecked( mLBL->isShowingCandidates() );
}
@@ -30,5 +32,7 @@
spinCandLine->value(),
spinCandPolygon->value());
+ mLBL->setShowingCandidates( chkShowCandidates->isChecked() );
+
accept();
}
Modified: branches/symbology-ng-branch/src/plugins/labeling/engineconfigdialog.ui
===================================================================
--- branches/symbology-ng-branch/src/plugins/labeling/engineconfigdialog.ui 2009-07-04 13:25:43 UTC (rev 11018)
+++ branches/symbology-ng-branch/src/plugins/labeling/engineconfigdialog.ui 2009-07-04 13:35:36 UTC (rev 11019)
@@ -27,7 +27,7 @@
<widget class="QComboBox" name="cboSearchMethod">
<item>
<property name="text">
- <string>Chain (fastest)</string>
+ <string>Chain (fast)</string>
</property>
</item>
<item>
@@ -45,6 +45,11 @@
<string>Popmusic Tabu Chain</string>
</property>
</item>
+ <item>
+ <property name="text">
+ <string>FALP (fastest)</string>
+ </property>
+ </item>
</widget>
</item>
</layout>
@@ -88,6 +93,9 @@
<property name="minimum">
<number>1</number>
</property>
+ <property name="maximum">
+ <number>999</number>
+ </property>
</widget>
</item>
<item row="1" column="0">
@@ -105,6 +113,9 @@
<property name="minimum">
<number>1</number>
</property>
+ <property name="maximum">
+ <number>999</number>
+ </property>
</widget>
</item>
<item row="2" column="0">
@@ -122,6 +133,9 @@
<property name="minimum">
<number>1</number>
</property>
+ <property name="maximum">
+ <number>999</number>
+ </property>
</widget>
</item>
</layout>
@@ -159,6 +173,13 @@
</spacer>
</item>
<item>
+ <widget class="QCheckBox" name="chkShowCandidates">
+ <property name="text">
+ <string>Show label candidates (for debugging)</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@@ -170,6 +191,14 @@
</item>
</layout>
</widget>
+ <tabstops>
+ <tabstop>cboSearchMethod</tabstop>
+ <tabstop>spinCandPoint</tabstop>
+ <tabstop>spinCandLine</tabstop>
+ <tabstop>spinCandPolygon</tabstop>
+ <tabstop>chkShowCandidates</tabstop>
+ <tabstop>buttonBox</tabstop>
+ </tabstops>
<resources/>
<connections>
<connection>
Modified: branches/symbology-ng-branch/src/plugins/labeling/labeling.cpp
===================================================================
--- branches/symbology-ng-branch/src/plugins/labeling/labeling.cpp 2009-07-04 13:25:43 UTC (rev 11018)
+++ branches/symbology-ng-branch/src/plugins/labeling/labeling.cpp 2009-07-04 13:35:36 UTC (rev 11019)
@@ -65,13 +65,46 @@
{
}
+/////////
+
+#include <qgsmaptool.h>
+#include <QMouseEvent>
+#include <QToolTip>
+
+class LabelingTool : public QgsMapTool
+{
+public:
+ LabelingTool(PalLabeling* lbl, QgsMapCanvas* canvas) : QgsMapTool(canvas), mLBL(lbl) {}
+
+ virtual void canvasPressEvent( QMouseEvent * e )
+ {
+ const QList<LabelCandidate>& cand = mLBL->candidates();
+ QPointF pt = e->posF();
+ for (int i = 0; i < cand.count(); i++)
+ {
+ const LabelCandidate& c = cand[i];
+ if (c.rect.contains(pt))
+ {
+ QToolTip::showText( mCanvas->mapToGlobal(e->pos()), QString::number(c.cost), mCanvas);
+ break;
+ }
+ }
+ }
+
+protected:
+ PalLabeling* mLBL;
+};
+
+///////////
+
+
/*
* Initialize the GUI interface for the plugin - this is only called once when the plugin is
* added to the plugin registry in the QGIS application.
*/
void Labeling::initGui()
{
- mLBL = new PalLabeling(mQGisIface->mapCanvas());
+ mLBL = new PalLabeling(mQGisIface->mapCanvas()->mapRenderer());
// Create the action for tool
mQActionPointer = new QAction( QIcon( ":/labeling/labeling.png" ), tr( "Labeling" ), this );
@@ -83,13 +116,19 @@
mQGisIface->addToolBarIcon( mQActionPointer );
mQGisIface->addPluginToMenu( tr( "&Labeling" ), mQActionPointer );
+ mActionTool = new QAction( "Ltool", this );
+ mQGisIface->addToolBarIcon( mActionTool );
+ connect( mActionTool, SIGNAL( triggered() ), this, SLOT( setTool() ) );
+
+ mTool = new LabelingTool(mLBL, mQGisIface->mapCanvas());
+
connect( mQGisIface->mapCanvas(), SIGNAL( renderComplete( QPainter * ) ), this, SLOT( doLabeling( QPainter * ) ) );
}
void Labeling::doLabeling( QPainter * painter )
{
- mLBL->doLabeling(painter);
+ mLBL->doLabeling(painter, mQGisIface->mapCanvas()->extent());
}
// Slot called when the menu item is triggered
@@ -119,14 +158,26 @@
}
}
+
+void Labeling::setTool()
+{
+ mQGisIface->mapCanvas()->setMapTool(mTool);
+}
+
// Unload the plugin by cleaning up the GUI
void Labeling::unload()
{
+ mQGisIface->mapCanvas()->unsetMapTool(mTool);
+ delete mTool;
+
// remove the GUI
mQGisIface->removePluginMenu( "&Labeling", mQActionPointer );
mQGisIface->removeToolBarIcon( mQActionPointer );
delete mQActionPointer;
+ mQGisIface->removeToolBarIcon( mActionTool );
+ delete mActionTool;
+
delete mLBL;
}
Modified: branches/symbology-ng-branch/src/plugins/labeling/labeling.h
===================================================================
--- branches/symbology-ng-branch/src/plugins/labeling/labeling.h 2009-07-04 13:25:43 UTC (rev 11018)
+++ branches/symbology-ng-branch/src/plugins/labeling/labeling.h 2009-07-04 13:35:36 UTC (rev 11019)
@@ -32,6 +32,7 @@
class QgisInterface;
class PalLabeling;
+class LabelingTool;
class Labeling: public QObject, public QgisPlugin
{
@@ -58,14 +59,20 @@
//! hook to renderComplete signal
void doLabeling(QPainter* painter);
+ //! start labeling map tool
+ void setTool();
+
private:
//! Pointer to the QGIS interface object
QgisInterface *mQGisIface;
//! Pointer to the qaction for this plugin
QAction * mQActionPointer;
+ QAction * mActionTool;
PalLabeling* mLBL;
+
+ LabelingTool* mTool;
};
#endif //Labeling_H
Modified: branches/symbology-ng-branch/src/plugins/labeling/pallabeling.cpp
===================================================================
--- branches/symbology-ng-branch/src/plugins/labeling/pallabeling.cpp 2009-07-04 13:25:43 UTC (rev 11018)
+++ branches/symbology-ng-branch/src/plugins/labeling/pallabeling.cpp 2009-07-04 13:35:36 UTC (rev 11019)
@@ -7,6 +7,8 @@
#include <pal/layer.h>
#include <pal/palgeometry.h>
#include <pal/palexception.h>
+#include <pal/problem.h>
+#include <pal/labelposition.h>
#include <geos_c.h>
@@ -15,12 +17,14 @@
#include <QByteArray>
#include <QString>
#include <QFontMetrics>
+#include <QTime>
+#include <QPainter>
#include <qgsvectorlayer.h>
#include <qgsmaplayerregistry.h>
#include <qgsvectordataprovider.h>
#include <qgsgeometry.h>
-#include <qgsmapcanvas.h>
+#include <qgsmaprenderer.h>
using namespace pal;
@@ -105,8 +109,8 @@
// -------------
-PalLabeling::PalLabeling(QgsMapCanvas* mapCanvas)
- : mMapCanvas(mapCanvas), mPal(NULL)
+PalLabeling::PalLabeling(QgsMapRenderer* mapRenderer)
+ : mMapRenderer(mapRenderer), mPal(NULL)
{
// find out engine defaults
@@ -121,8 +125,11 @@
case POPMUSIC_TABU: mSearch = Popmusic_Tabu; break;
case POPMUSIC_CHAIN: mSearch = Popmusic_Chain; break;
case POPMUSIC_TABU_CHAIN: mSearch = Popmusic_Tabu_Chain; break;
+ case FALP: mSearch = Falp; break;
}
+ mShowingCandidates = FALSE;
+
initPal();
}
@@ -217,7 +224,7 @@
lyr->fieldIndex = fldIndex;
lyr->fontMetrics = new QFontMetrics(lyr->textFont);
lyr->fontBaseline = lyr->fontMetrics->boundingRect("X").bottom(); // dummy text to find out how many pixels of the text are below the baseline
- lyr->xform = thisClass->mMapCanvas->mapRenderer()->coordinateTransform();
+ lyr->xform = thisClass->mMapRenderer->coordinateTransform();
lyr->ptZero = lyr->xform->toMapCoordinates( 0,0 );
return 1; // init successful
@@ -245,6 +252,7 @@
case Popmusic_Tabu: s = POPMUSIC_TABU; break;
case Popmusic_Chain: s = POPMUSIC_CHAIN; break;
case Popmusic_Tabu_Chain: s = POPMUSIC_TABU_CHAIN; break;
+ case Falp: s = FALP; break;
}
mPal->setSearch(s);
//mPal->setSearch(FALP);
@@ -257,7 +265,7 @@
-void PalLabeling::doLabeling(QPainter* painter)
+void PalLabeling::doLabeling(QPainter* painter, QgsRectangle extent)
{
QTime t;
@@ -274,13 +282,23 @@
// do the labeling itself
double scale = 1; // scale denominator
- QgsRectangle r = mMapCanvas->extent();
+ QgsRectangle r = extent;
double bbox[] = { r.xMinimum(), r.yMinimum(), r.xMaximum(), r.yMaximum() };
std::list<Label*>* labels;
+ pal::Problem* problem;
try
{
- labels = mPal->labeller(scale, bbox, NULL, false);
+ //labels = mPal->labeller(scale, bbox, NULL, false);
+ problem = mPal->extractProblem(scale, bbox);
+ if ( problem )
+ {
+ // TODO: other methods
+ problem->chain_search();
+ labels = problem->getSolution(false);
+ }
+ else
+ labels = new std::list<Label*>();
}
catch ( std::exception& e )
{
@@ -288,11 +306,46 @@
return;
}
+ const QgsMapToPixel* xform = mMapRenderer->coordinateTransform();
+
+ // draw rectangles with all candidates
+ // this is done before actual solution of the problem
+ // before number of candidates gets reduced
+ mCandidates.clear();
+ if (mShowingCandidates && problem)
+ {
+ painter->setPen(QColor(0,0,0,64));
+ painter->setBrush(Qt::NoBrush);
+ for (int i = 0; i < problem->getNumFeatures(); i++)
+ {
+ for (int j = 0; j < problem->getFeatureCandidateCount(i); j++)
+ {
+ pal::LabelPosition* lp = problem->getFeatureCandidate(i, j);
+
+ QgsPoint outPt = xform->transform(lp->getX(), lp->getY());
+ QgsPoint outPt2 = xform->transform(lp->getX()+lp->getWidth(), lp->getY()+lp->getHeight());
+
+ painter->save();
+ painter->translate( QPointF(outPt.x(), outPt.y()) );
+ painter->rotate(-lp->getAlpha() * 180 / M_PI );
+ QRectF rect(0,0, outPt2.x()-outPt.x(), outPt2.y()-outPt.y());
+ painter->drawRect(rect);
+ painter->restore();
+
+ // save the rect
+ rect.moveTo(outPt.x(),outPt.y());
+ mCandidates.append( LabelCandidate(rect, lp->getCost() * 1000) );
+ }
+ }
+ }
+
+ // find the solution
+ labels = mPal->solveProblem( problem );
+
std::cout << "LABELING work: " << t.elapsed() << "ms ... labels# " << labels->size() << std::endl;
t.restart();
// draw the labels
- const QgsMapToPixel* xform = mMapCanvas->mapRenderer()->coordinateTransform();
std::list<Label*>::iterator it = labels->begin();
for ( ; it != labels->end(); ++it)
{
@@ -317,6 +370,7 @@
std::cout << "LABELING draw: " << t.elapsed() << "ms" << std::endl;
+ delete problem;
delete labels;
// delete all allocated geometries for features
Modified: branches/symbology-ng-branch/src/plugins/labeling/pallabeling.h
===================================================================
--- branches/symbology-ng-branch/src/plugins/labeling/pallabeling.h 2009-07-04 13:25:43 UTC (rev 11018)
+++ branches/symbology-ng-branch/src/plugins/labeling/pallabeling.h 2009-07-04 13:35:36 UTC (rev 11019)
@@ -2,12 +2,14 @@
#define PALLABELING_H
class QPainter;
-class QgsMapCanvas;
+class QgsMapRenderer;
+class QgsRectangle;
#include <QString>
#include <QFont>
#include <QColor>
#include <QList>
+#include <QRectF>
namespace pal
{
@@ -62,13 +64,22 @@
QList<MyLabel*> geometries;
};
+class LabelCandidate
+{
+public:
+ LabelCandidate(QRectF r, double c): rect(r), cost(c) {}
+
+ QRectF rect;
+ double cost;
+};
+
class PalLabeling
{
public:
- PalLabeling(QgsMapCanvas* mapCanvas);
+ PalLabeling(QgsMapRenderer* renderer);
~PalLabeling();
- void doLabeling(QPainter* painter);
+ void doLabeling(QPainter* painter, QgsRectangle extent);
void addLayer(LayerSettings layerSettings);
@@ -79,11 +90,14 @@
void numCandidatePositions(int& candPoint, int& candLine, int& candPolygon);
void setNumCandidatePositions(int candPoint, int candLine, int candPolygon);
- enum Search { Chain, Popmusic_Tabu, Popmusic_Chain, Popmusic_Tabu_Chain };
+ enum Search { Chain, Popmusic_Tabu, Popmusic_Chain, Popmusic_Tabu_Chain, Falp };
void setSearchMethod(Search s);
Search searchMethod() const;
+ bool isShowingCandidates() const { return mShowingCandidates; }
+ void setShowingCandidates(bool showing) { mShowingCandidates = showing; }
+ const QList<LabelCandidate>& candidates() { return mCandidates; }
//! hook called when drawing layer before issuing select()
static int prepareLayerHook(void* context, void* layerContext, int& attrIndex);
@@ -96,11 +110,15 @@
protected:
QList<LayerSettings> mLayers;
- QgsMapCanvas* mMapCanvas;
+ QgsMapRenderer* mMapRenderer;
int mCandPoint, mCandLine, mCandPolygon;
Search mSearch;
pal::Pal* mPal;
+
+ // list of candidates from last labeling
+ QList<LabelCandidate> mCandidates;
+ bool mShowingCandidates;
};
#endif // PALLABELING_H
More information about the QGIS-commit
mailing list