mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-26 00:02:08 -05:00
git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@4409 c8812cc2-4d05-0410-92ff-de0c093fc19c
371 lines
10 KiB
C++
371 lines
10 KiB
C++
#include <cmath>
|
|
|
|
#include <qtoolbutton.h>
|
|
#include <qpushbutton.h>
|
|
#include <qcombobox.h>
|
|
#include <QFileDialog>
|
|
#include <q3frame.h>
|
|
#include <qlayout.h>
|
|
#include <qlineedit.h>
|
|
#include <qmessagebox.h>
|
|
//Added by qt3to4:
|
|
#include <QPixmap>
|
|
#include <QTextStream>
|
|
#include <QHBoxLayout>
|
|
//#include <Q3HBoxLayout>
|
|
|
|
#include "datapointacetate.h"
|
|
#include "qgspointdialog.h"
|
|
#include "mapcoordsdialog.h"
|
|
#include "qgsleastsquares.h"
|
|
#include "qgsimagewarper.h"
|
|
#include "qgsgeorefwarpoptionsdialog.h"
|
|
|
|
#include "zoom_in.xpm"
|
|
#include "zoom_out.xpm"
|
|
#include "pan.xpm"
|
|
#include "add_point.xpm"
|
|
|
|
QgsPointDialog::QgsPointDialog() {
|
|
|
|
}
|
|
|
|
|
|
QgsPointDialog::QgsPointDialog(QgsRasterLayer* layer, QWidget* parent,
|
|
const char* name, bool modal, Qt::WFlags fl)
|
|
: QgsPointDialogBase(),
|
|
// commented out during qt4 port - FIXME tim
|
|
//: QgsPointDialogBase(parent, name, modal, fl),
|
|
mCursor(NULL),
|
|
mLayer(layer)
|
|
{
|
|
|
|
// set up the canvas
|
|
QHBoxLayout* layout = new QHBoxLayout(canvasFrame);
|
|
layout->setAutoAdd(true);
|
|
mCanvas = new QgsMapCanvas(canvasFrame, "georefCanvas");
|
|
mCanvas->setBackgroundColor(Qt::white);
|
|
mCanvas->setMinimumWidth(400);
|
|
mCanvas->freeze(true);
|
|
mCanvas->addLayer(mLayer);
|
|
tbnAddPoint->setOn(true);
|
|
|
|
// load previously added points
|
|
QFile pointFile(mLayer->source() + ".points");
|
|
if (pointFile.open(QIODevice::ReadOnly)) {
|
|
QTextStream points(&pointFile);
|
|
QString tmp;
|
|
points>>tmp>>tmp>>tmp>>tmp;
|
|
while (!points.atEnd()) {
|
|
double mapX, mapY, pixelX, pixelY;
|
|
points>>mapX>>mapY>>pixelX>>pixelY;
|
|
QgsPoint mapCoords(mapX, mapY);
|
|
QgsPoint pixelCoords(pixelX, pixelY);
|
|
addPoint(pixelCoords, mapCoords);
|
|
}
|
|
}
|
|
|
|
mCanvas->setExtent(mLayer->extent());
|
|
mCanvas->freeze(false);
|
|
connect(mCanvas, SIGNAL(xyClickCoordinates(QgsPoint&)),
|
|
this, SLOT(handleCanvasClick(QgsPoint&)));
|
|
leSelectWorldFile->setText(guessWorldFileName(mLayer->source()));
|
|
}
|
|
|
|
|
|
QgsPointDialog::~QgsPointDialog() {
|
|
|
|
}
|
|
|
|
|
|
void QgsPointDialog::handleCanvasClick(QgsPoint& pixelCoords) {
|
|
if (tbnAddPoint->isChecked())
|
|
showCoordDialog(pixelCoords);
|
|
else if (tbnDeletePoint->isChecked())
|
|
deleteDataPoint(pixelCoords);
|
|
}
|
|
|
|
|
|
void QgsPointDialog::addPoint(const QgsPoint& pixelCoords,
|
|
const QgsPoint& mapCoords) {
|
|
mPixelCoords.push_back(pixelCoords);
|
|
mMapCoords.push_back(mapCoords);
|
|
static int acetateCounter = 0;
|
|
mAcetateIDs.push_back(QString("%1").arg(++acetateCounter));
|
|
mCanvas->addAcetateObject(mAcetateIDs[mAcetateIDs.size() - 1],
|
|
new DataPointAcetate(pixelCoords, mapCoords));
|
|
mCanvas->refresh();
|
|
}
|
|
|
|
|
|
void QgsPointDialog::pbnCancel_clicked() {
|
|
delete mCanvas;
|
|
delete mLayer;
|
|
reject();
|
|
}
|
|
|
|
|
|
void QgsPointDialog::pbnGenerateWorldFile_clicked() {
|
|
if (generateWorldFile()) {
|
|
delete mCanvas;
|
|
delete mLayer;
|
|
accept();
|
|
}
|
|
}
|
|
|
|
|
|
void QgsPointDialog::pbnGenerateAndLoad_clicked() {
|
|
if (generateWorldFile()) {
|
|
delete mCanvas;
|
|
if (cmbTransformType->currentItem() == 0)
|
|
emit loadLayer(mLayer->source());
|
|
else
|
|
emit loadLayer(leSelectModifiedRaster->text());
|
|
delete mLayer;
|
|
accept();
|
|
}
|
|
}
|
|
|
|
|
|
void QgsPointDialog::pbnSelectWorldFile_clicked() {
|
|
QString filename =
|
|
QFileDialog::getSaveFileName(this,
|
|
"Choose a name for the world file",
|
|
".");
|
|
leSelectWorldFile->setText(filename);
|
|
}
|
|
|
|
|
|
void QgsPointDialog::pbnSelectModifiedRaster_clicked() {
|
|
QString filename =
|
|
QFileDialog::getSaveFileName(this,
|
|
"Choose a name for the world file",
|
|
".");
|
|
if (filename.right(4) != ".tif")
|
|
filename += ".tif";
|
|
leSelectModifiedRaster->setText(filename);
|
|
leSelectWorldFile->setText(guessWorldFileName(filename));
|
|
}
|
|
|
|
|
|
bool QgsPointDialog::generateWorldFile() {
|
|
QgsPoint origin(0, 0);
|
|
double pixelSize = 1;
|
|
double rotation = 0;
|
|
|
|
// compute the parameters using the least squares method
|
|
// (might throw std::domain_error)
|
|
try {
|
|
if (cmbTransformType->currentItem() == 0)
|
|
QgsLeastSquares::linear(mMapCoords, mPixelCoords, origin, pixelSize);
|
|
else if (cmbTransformType->currentItem() == 1) {
|
|
int res =
|
|
QMessageBox::warning(this, "Warning",
|
|
"A Helmert transform requires modifications in "
|
|
"the raster layer.\nThe modifed raster will be "
|
|
"saved in a new file and a world file will be "
|
|
"generated for this new file instead.\nAre you "
|
|
"sure that this is what you want?",
|
|
QMessageBox::No, QMessageBox::Yes);
|
|
if (res == QMessageBox::No)
|
|
return false;
|
|
QgsLeastSquares::helmert(mMapCoords, mPixelCoords,
|
|
origin, pixelSize, rotation);
|
|
}
|
|
else if (cmbTransformType->currentItem() == 2) {
|
|
QMessageBox::critical(this, "Not implemented!",
|
|
"An affine transform requires changing the "
|
|
"original raster file. This is not yet "
|
|
"supported.");
|
|
return false;
|
|
}
|
|
}
|
|
catch (std::domain_error& e) {
|
|
QMessageBox::critical(this, "Error", QString(e.what()));
|
|
return false;
|
|
}
|
|
|
|
// warp the raster if needed
|
|
double xOffset, yOffset;
|
|
if (rotation != 0) {
|
|
QgsGeorefWarpOptionsDialog d(this);
|
|
d.exec();
|
|
bool useZeroForTrans;
|
|
QgsImageWarper::ResamplingMethod resampling;
|
|
QgsImageWarper warper(-rotation);
|
|
d.getWarpOptions(resampling, useZeroForTrans);
|
|
warper.warp(mLayer->source(), leSelectModifiedRaster->text(),
|
|
xOffset, yOffset, resampling, useZeroForTrans);
|
|
}
|
|
|
|
// write the world file
|
|
QFile file(leSelectWorldFile->text());
|
|
if (!file.open(QIODevice::WriteOnly)) {
|
|
QMessageBox::critical(this, "Error",
|
|
"Could not write to " + leSelectWorldFile->text());
|
|
return false;
|
|
}
|
|
QTextStream stream(&file);
|
|
stream<<pixelSize<<endl
|
|
<<0<<endl
|
|
<<0<<endl
|
|
<<-pixelSize<<endl
|
|
<<(origin.x() - xOffset * pixelSize)<<endl
|
|
<<(origin.y() + yOffset * pixelSize)<<endl;
|
|
|
|
// write the data points in case we need them later
|
|
QFile pointFile(mLayer->source() + ".points");
|
|
if (pointFile.open(QIODevice::WriteOnly)) {
|
|
QTextStream points(&pointFile);
|
|
points<<"mapX\tmapY\tpixelX\tpixelY"<<endl;
|
|
for (int i = 0; i < mMapCoords.size(); ++i) {
|
|
points<<(QString("%1\t%2\t%3\t%4").
|
|
arg(mMapCoords[i].x()).arg(mMapCoords[i].y()).
|
|
arg(mPixelCoords[i].x()).arg(mPixelCoords[i].y()))<<endl;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
void QgsPointDialog::tbnZoomIn_changed(int state) {
|
|
if (state == QCheckBox::On) {
|
|
tbnZoomOut->setOn(false);
|
|
tbnPan->setOn(false);
|
|
tbnAddPoint->setOn(false);
|
|
tbnDeletePoint->setOn(false);
|
|
mCanvas->setMapTool(QGis::ZoomIn);
|
|
delete mCursor;
|
|
QPixmap pix((const char **)zoom_in2);
|
|
mCursor = new QCursor(pix, 7, 7);
|
|
mCanvas->setCursor(*mCursor);
|
|
}
|
|
}
|
|
|
|
|
|
void QgsPointDialog::tbnZoomOut_changed(int state) {
|
|
if (state == QCheckBox::On) {
|
|
tbnZoomIn->setOn(false);
|
|
tbnPan->setOn(false);
|
|
tbnAddPoint->setOn(false);
|
|
tbnDeletePoint->setOn(false);
|
|
mCanvas->setMapTool(QGis::ZoomOut);
|
|
delete mCursor;
|
|
QPixmap pix((const char **)zoom_out);
|
|
mCursor = new QCursor(pix, 7, 7);
|
|
mCanvas->setCursor(*mCursor);
|
|
}
|
|
}
|
|
|
|
|
|
void QgsPointDialog::tbnZoomToLayer_clicked() {
|
|
mCanvas->setExtent(mLayer->extent());
|
|
mCanvas->refresh();
|
|
}
|
|
|
|
|
|
void QgsPointDialog::tbnPan_changed(int state) {
|
|
if (state == QCheckBox::On) {
|
|
tbnZoomIn->setOn(false);
|
|
tbnZoomOut->setOn(false);
|
|
tbnAddPoint->setOn(false);
|
|
tbnDeletePoint->setOn(false);
|
|
mCanvas->setMapTool(QGis::Pan);
|
|
delete mCursor;
|
|
QPixmap pix((const char **)pan);
|
|
mCursor = new QCursor(pix, 7, 7);
|
|
mCanvas->setCursor(*mCursor);
|
|
}
|
|
}
|
|
|
|
|
|
void QgsPointDialog::tbnAddPoint_changed(int state) {
|
|
if (state == QCheckBox::On) {
|
|
tbnZoomIn->setOn(false);
|
|
tbnZoomOut->setOn(false);
|
|
tbnPan->setOn(false);
|
|
tbnDeletePoint->setOn(false);
|
|
mCanvas->setMapTool(QGis::EmitPoint);
|
|
delete mCursor;
|
|
QPixmap pix((const char **)add_point);
|
|
mCursor = new QCursor(pix, 7, 7);
|
|
mCanvas->setCursor(*mCursor);
|
|
}
|
|
}
|
|
|
|
|
|
void QgsPointDialog::tbnDeletePoint_changed(int state) {
|
|
if (state == QCheckBox::On) {
|
|
tbnZoomIn->setOn(false);
|
|
tbnZoomOut->setOn(false);
|
|
tbnPan->setOn(false);
|
|
tbnAddPoint->setOn(false);
|
|
mCanvas->setMapTool(QGis::EmitPoint);
|
|
}
|
|
}
|
|
|
|
|
|
void QgsPointDialog::showCoordDialog(QgsPoint& pixelCoords) {
|
|
MapCoordsDialog* mcd = new MapCoordsDialog(pixelCoords, this, NULL, true);
|
|
connect(mcd, SIGNAL(pointAdded(const QgsPoint&, const QgsPoint&)),
|
|
this, SLOT(addPoint(const QgsPoint&, const QgsPoint&)));
|
|
mcd->show();
|
|
}
|
|
|
|
|
|
void QgsPointDialog::deleteDataPoint(QgsPoint& pixelCoords) {
|
|
std::vector<QgsPoint>::iterator pixIter = mPixelCoords.begin();
|
|
std::vector<QgsPoint>::iterator mapIter = mMapCoords.begin();
|
|
std::vector<QString>::iterator idIter = mAcetateIDs.begin();
|
|
|
|
for ( ; pixIter != mPixelCoords.end(); ++pixIter, ++mapIter, ++idIter) {
|
|
if (std::sqrt(std::pow(pixIter->x() - pixelCoords.x(), 2) +
|
|
std::pow(pixIter->y() - pixelCoords.y(), 2)) <
|
|
5 * mCanvas->mupp()) {
|
|
mCanvas->removeAcetateObject(*idIter);
|
|
mAcetateIDs.erase(idIter);
|
|
mPixelCoords.erase(pixIter);
|
|
mMapCoords.erase(mapIter);
|
|
mCanvas->refresh();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void QgsPointDialog::enableRelevantControls() {
|
|
if (cmbTransformType->currentItem() == 0) {
|
|
leSelectModifiedRaster->setEnabled(false);
|
|
pbnSelectModifiedRaster->setEnabled(false);
|
|
}
|
|
else {
|
|
leSelectModifiedRaster->setEnabled(true);
|
|
pbnSelectModifiedRaster->setEnabled(true);
|
|
}
|
|
|
|
if ((cmbTransformType->currentItem() == 0 &&
|
|
!leSelectWorldFile->text().isEmpty()) ||
|
|
(!leSelectWorldFile->text().isEmpty() &&
|
|
!leSelectModifiedRaster->text().isEmpty())) {
|
|
pbnGenerateWorldFile->setEnabled(true);
|
|
pbnGenerateAndLoad->setEnabled(true);
|
|
}
|
|
else {
|
|
pbnGenerateWorldFile->setEnabled(false);
|
|
pbnGenerateAndLoad->setEnabled(false);
|
|
}
|
|
}
|
|
|
|
|
|
QString QgsPointDialog::guessWorldFileName(const QString& raster) {
|
|
int point = raster.findRev('.');
|
|
QString worldfile = "";
|
|
if (point != -1 && point != raster.length() - 1) {
|
|
worldfile = raster.left(point + 1);
|
|
worldfile += raster.at(point + 1);
|
|
worldfile += raster.at(raster.length() - 1);
|
|
worldfile += 'w';
|
|
}
|
|
return worldfile;
|
|
}
|