1
/***************************************************************************
3
Import tool for various worldmap analysis output files
8
copyright : (C) 2004 by Tim Sutton
9
email : tim@linfiniti.com
11
***************************************************************************/
13
/***************************************************************************
15
* This program is free software; you can redistribute it and/or modify *
16
* it under the terms of the GNU General Public License as published by *
17
* the Free Software Foundation; either version 2 of the License, or *
18
* (at your option) any later version. *
20
***************************************************************************/
21
/* $Id: plugin.cpp 6301 2006-12-22 07:43:47Z g_j_m $ */
27
#include <qgsmaplayer.h>
29
#include "qgsproject.h"
30
#include "qgsmapcanvas.h"
31
#include "qgsapplication.h"
43
#include "plugingui.h"
45
// xpm for creating the toolbar icon
49
#define QGISEXTERN extern "C" __declspec( dllexport )
51
#define QGISEXTERN extern "C"
55
static const char * const ident_ = "$Id: plugin.cpp 6301 2006-12-22 07:43:47Z g_j_m $";
57
static const QString name_ = QObject::tr("NorthArrow");
58
static const QString description_ = QObject::tr("Displays a north arrow overlayed onto the map");
59
static const QString version_ = QObject::tr("Version 0.1");
60
static const QgisPlugin::PLUGINTYPE type_ = QgisPlugin::UI;
62
const double QgsNorthArrowPlugin::PI = 3.14159265358979323846;
63
// const double QgsNorthArrowPlugin::DEG2RAD = 0.0174532925199433;
64
const double QgsNorthArrowPlugin::TOL = 1e-8;
68
* Constructor for the plugin. The plugin is passed a pointer to the main app
69
* and an interface object that provides access to exposed functions in QGIS.
70
* @param qgis Pointer to the QGIS main window
71
* @param _qI Pointer to the QGIS interface object
73
QgsNorthArrowPlugin::QgsNorthArrowPlugin(QgisApp * theQGisApp,
74
QgisIface * theQgisInterFace):
75
QgisPlugin(name_,description_,version_,type_),
76
qgisMainWindowPointer(theQGisApp),
77
qGisInterface(theQgisInterFace)
81
mPlacementLabels << tr("Bottom Left") << tr("Top Left")
82
<< tr("Top Right") << tr("Bottom Right");
85
QgsNorthArrowPlugin::~QgsNorthArrowPlugin()
90
* Initialize the GUI interface for the plugin
92
void QgsNorthArrowPlugin::initGui()
94
// Create the action for tool
95
myQActionPointer = new QAction(QIcon(icon), tr("&North Arrow"), this);
96
myQActionPointer->setWhatsThis(tr("Creates a north arrow that is displayed on the map canvas"));
97
// Connect the action to the run
98
connect(myQActionPointer, SIGNAL(activated()), this, SLOT(run()));
99
//render the arrow each time the map is rendered
100
connect(qGisInterface->getMapCanvas(), SIGNAL(renderComplete(QPainter *)), this, SLOT(renderNorthArrow(QPainter *)));
101
//this resets this plugin up if a project is loaded
102
connect(qgisMainWindowPointer, SIGNAL(projectRead()), this, SLOT(projectRead()));
103
// Add the icon to the toolbar & appropriate menu
104
qGisInterface->addToolBarIcon(myQActionPointer);
105
qGisInterface->addPluginMenu(tr("&Decorations"), myQActionPointer);
112
void QgsNorthArrowPlugin::projectRead()
115
std::cout << "+++++++++ north arrow plugin - project read slot called...." << std::endl;
117
//default text to start with - try to fetch it from qgsproject
119
mRotationInt = QgsProject::instance()->readNumEntry("NorthArrow","/Rotation",0);
120
mPlacementIndex = QgsProject::instance()->readNumEntry("NorthArrow","/Placement",0);
121
mEnable = QgsProject::instance()->readBoolEntry("NorthArrow","/Enabled",true);
122
mAutomatic = QgsProject::instance()->readBoolEntry("NorthArrow","/Automatic",true);
125
//method defined in interface
126
void QgsNorthArrowPlugin::help()
131
// Slot called when the buffer menu item is activated
132
void QgsNorthArrowPlugin::run()
134
QgsNorthArrowPluginGui *myPluginGui = new QgsNorthArrowPluginGui(qgisMainWindowPointer, QgisGui::ModalDialogFlags);
135
//overides function by the same name created in .ui
136
myPluginGui->setRotation(mRotationInt);
137
myPluginGui->setPlacementLabels(mPlacementLabels);
138
myPluginGui->setPlacement(mPlacementIndex);
139
myPluginGui->setEnabled(mEnable);
140
myPluginGui->setAutomatic(mAutomatic);
142
//listen for when the layer has been made so we can draw it
143
connect(myPluginGui, SIGNAL(rotationChanged(int)), this, SLOT(rotationChanged(int)));
144
connect(myPluginGui, SIGNAL(changePlacement(int)), this, SLOT(setPlacement(int)));
145
connect(myPluginGui, SIGNAL(enableAutomatic(bool)), this, SLOT(setAutomatic(bool)));
146
connect(myPluginGui, SIGNAL(enableNorthArrow(bool)), this, SLOT(setEnabled(bool)));
147
connect(myPluginGui, SIGNAL(needToRefresh()), this, SLOT(refreshCanvas()));
151
//! Refresh the map display using the mapcanvas exported via the plugin interface
152
void QgsNorthArrowPlugin::refreshCanvas()
154
qGisInterface->getMapCanvas()->refresh();
157
void QgsNorthArrowPlugin::renderNorthArrow(QPainter * theQPainter)
160
std::cout << "Rendering n-arrow" << std::endl;
162
//Large IF statement controlled by enable check box
165
QPixmap myQPixmap; //to store the north arrow image in
167
QString myFileNameQString = QgsApplication::pkgDataPath() +
168
"/images/north_arrows/default.png";
170
//std::cout << "Trying to load " << myFileNameQString << std::cout;
171
if (myQPixmap.load(myFileNameQString))
174
double centerXDouble = myQPixmap.width()/2;
175
double centerYDouble = myQPixmap.height()/2;
176
//save the current canvas rotation
179
//work out how to shift the image so that it rotates
180
// properly about its center
181
//(x cos a + y sin a - x, -x sin a + y cos a - y)
184
// could move this call to somewhere else so that it is only
185
// called when the projection or map extent changes
187
calculateNorthDirection();
189
double myRadiansDouble = mRotationInt * PI / 180.0;
190
int xShift = static_cast<int>((
191
(centerXDouble * cos(myRadiansDouble)) +
192
(centerYDouble * sin(myRadiansDouble))
194
int yShift = static_cast<int>((
195
(-centerXDouble * sin(myRadiansDouble)) +
196
(centerYDouble * cos(myRadiansDouble))
199
// need width/height of paint device
200
int myHeight = theQPainter->device()->height();
201
int myWidth = theQPainter->device()->width();
204
std::cout << "Rendering n-arrow at " << mPlacementLabels.at(mPlacementIndex).toLocal8Bit().data() << std::endl;
206
//Determine placement of label from form combo box
207
switch (mPlacementIndex)
209
case 0: // Bottom Left
210
theQPainter->translate(0,myHeight-myQPixmap.height());
213
//no need to translate for TL corner because we're already at the origin
214
theQPainter->translate(0, 0);
217
theQPainter->translate(myWidth-myQPixmap.width(),0);
219
case 3: // Bottom Right
220
theQPainter->translate(myWidth-myQPixmap.width(),
221
myHeight-myQPixmap.height());
224
std::cout << "Unable to determine where to put north arrow so defaulting to top left"
227
//rotate the canvas by the north arrow rotation amount
228
theQPainter->rotate( mRotationInt );
229
//Now we can actually do the drawing, and draw a smooth north arrow even when rotated
230
theQPainter->setRenderHint(QPainter::SmoothPixmapTransform);
231
theQPainter->drawPixmap(xShift,yShift,myQPixmap);
233
//unrotate the canvas again
234
theQPainter->restore();
238
QFont myQFont("time", 12, QFont::Bold);
239
theQPainter->setFont(myQFont);
240
theQPainter->setPen(Qt::black);
241
theQPainter->drawText(10, 20, QString(tr("North arrow pixmap not found")));
246
// Unload the plugin by cleaning up the GUI
247
void QgsNorthArrowPlugin::unload()
250
qGisInterface->removePluginMenu(tr("&Decorations"), myQActionPointer);
251
qGisInterface->removeToolBarIcon(myQActionPointer);
252
// remove the northarrow from the canvas
253
disconnect(qGisInterface->getMapCanvas(), SIGNAL(renderComplete(QPainter *)),
254
this, SLOT(renderNorthArrow(QPainter *)));
257
delete myQActionPointer;
261
void QgsNorthArrowPlugin::rotationChanged(int theInt)
263
mRotationInt = theInt;
264
QgsProject::instance()->writeEntry("NorthArrow","/Rotation", mRotationInt );
267
//! set placement of north arrow
268
void QgsNorthArrowPlugin::setPlacement(int placementIndex)
270
mPlacementIndex = placementIndex;
271
QgsProject::instance()->writeEntry("NorthArrow","/Placement", mPlacementIndex);
274
void QgsNorthArrowPlugin::setEnabled(bool theBool)
277
QgsProject::instance()->writeEntry("NorthArrow","/Enabled", mEnable );
280
void QgsNorthArrowPlugin::setAutomatic(bool theBool)
282
mAutomatic = theBool;
283
QgsProject::instance()->writeEntry("NorthArrow","/Automatic", mAutomatic );
285
calculateNorthDirection();
288
bool QgsNorthArrowPlugin::calculateNorthDirection()
290
QgsMapCanvas& mapCanvas = *(qGisInterface->getMapCanvas());
292
bool goodDirn = false;
294
if (mapCanvas.layerCount() > 0)
296
// Grab an SRS from any layer
297
QgsMapLayer& mapLayer = *(mapCanvas.getZpos(0));
298
QgsSpatialRefSys& outputSRS = mapLayer.coordinateTransform()->destSRS();
300
if (outputSRS.isValid() && !outputSRS.geographicFlag())
302
// Use a geographic SRS to get lat/long to work out direction
303
QgsSpatialRefSys ourSRS;
304
ourSRS.createFromProj4("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs");
305
assert(ourSRS.isValid());
307
QgsCoordinateTransform transform(outputSRS, ourSRS);
309
QgsRect extent = mapCanvas.extent();
310
QgsPoint p1(extent.center());
311
// A point a bit above p1. XXX assumes that y increases up!!
312
// May need to involve the maptopixel transform if this proves
314
QgsPoint p2(p1.x(), p1.y() + extent.height() * 0.25);
316
// project p1 and p2 to geographic coords
319
p1 = transform.transform(p1);
320
p2 = transform.transform(p2);
322
catch (QgsException &e)
328
// Work out the value of the initial heading one takes to go
329
// from point p1 to point p2. The north direction is then that
330
// many degrees anti-clockwise or vertical.
332
// Take some care to not divide by zero, etc, and ensure that we
333
// get sensible results for all possible values for p1 and p2.
338
// convert to radians for the equations below
339
p1.multiply(PI/180.0);
340
p2.multiply(PI/180.0);
342
double y = sin(p2.x() - p1.x()) * cos(p2.y());
343
double x = cos(p1.y()) * sin(p2.y()) -
344
sin(p1.y()) * cos(p2.y()) * cos(p2.x()-p1.x());
351
angle = PI - atan(-y/x);
360
angle = atan(y/x) - PI;
372
angle = 0.0; // p1 = p2
376
// And set the angle of the north arrow. Perhaps do something
377
// different if goodDirn = false.
378
mRotationInt = static_cast<int>(round(fmod(360.0-angle*180.0/PI, 360.0)));
382
// For geographic SRS and for when there are no layers, set the
383
// direction back to the default
395
* Required extern functions needed for every plugin
396
* These functions can be called prior to creating an instance
397
* of the plugin class
399
// Class factory to return a new instance of the plugin class
400
QGISEXTERN QgisPlugin * classFactory(QgisApp * theQGisAppPointer, QgisIface * theQgisInterfacePointer)
402
return new QgsNorthArrowPlugin(theQGisAppPointer, theQgisInterfacePointer);
405
// Return the name of the plugin - note that we do not user class members as
406
// the class may not yet be insantiated when this method is called.
407
QGISEXTERN QString name()
412
// Return the description
413
QGISEXTERN QString description()
418
// Return the type (either UI or MapLayer plugin)
419
QGISEXTERN int type()
424
// Return the version number for the plugin
425
QGISEXTERN QString version()
431
QGISEXTERN void unload(QgisPlugin * thePluginPointer)
433
delete thePluginPointer;